Skip to content

Commit

Permalink
Code updates
Browse files Browse the repository at this point in the history
  • Loading branch information
martinrybak committed May 15, 2024
1 parent 2d6242c commit 3b556d1
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 87 deletions.
2 changes: 1 addition & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
include: package:pedantic/analysis_options.yaml
include: package:flutter_lints/flutter.yaml
42 changes: 22 additions & 20 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ class Home extends StatelessWidget {
children: <Widget>[
Container(height: 50, child: Center(child: GoodButton())),
Container(height: 50, child: Center(child: BadButton())),
RaisedButton(
TextButton(
child: Text('Good screen example'),
onPressed: () {
Navigator.of(context).pushNamed(GoodScreen.routeName);
},
),
RaisedButton(
TextButton(
child: Text('Bad screen example'),
onPressed: () {
Navigator.of(context).pushNamed(BadScreen.routeName);
Expand All @@ -64,7 +64,7 @@ class GoodButton extends StatelessWidget {
Widget build(BuildContext context) {
return Futuristic<int>(
futureBuilder: () => goodFuture(1, 2),
initialBuilder: (_, start) => RaisedButton(child: Text('Good button example'), onPressed: start),
initialBuilder: (_, start) => TextButton(child: Text('Good button example'), onPressed: start),
busyBuilder: (_) => CircularProgressIndicator(),
dataBuilder: (_, data) => Text(data.toString()),
);
Expand All @@ -76,9 +76,9 @@ class BadButton extends StatelessWidget {
Widget build(BuildContext context) {
return Futuristic<int>(
futureBuilder: () => badFuture(1, 2),
initialBuilder: (_, start) => RaisedButton(child: Text('Bad button example'), onPressed: start),
busyBuilder: (_) => CircularProgressIndicator(),
errorBuilder: (_, error, retry) => RaisedButton(child: Text('Sorry! Try again'), onPressed: retry),
initialBuilder: (_, start) => TextButton(child: Text('Bad button example'), onPressed: start),
busyBuilder: (_) => const CircularProgressIndicator(),
errorBuilder: (_, error, retry) => TextButton(child: Text('Sorry! Try again'), onPressed: retry),
);
}
}
Expand Down Expand Up @@ -112,21 +112,23 @@ class BadScreen extends StatelessWidget {
autoStart: true,
futureBuilder: () => badFuture(1, 2),
busyBuilder: (_) => CircularProgressIndicator(),
onError: (error, retry) {
showDialog(
onError: (error, retry) async {
await showDialog(
context: context,
child: AlertDialog(
content: Text('Sorry! Try again'),
actions: <Widget>[
FlatButton(
child: Text('RETRY'),
onPressed: () {
Navigator.of(context).pop();
retry();
},
)
],
),
builder: (innerContext) {
return AlertDialog(
content: Text('Sorry! Try again'),
actions: <Widget>[
TextButton(
child: Text('RETRY'),
onPressed: () {
Navigator.of(innerContext).pop();
retry();
},
)
],
);
},
);
},
),
Expand Down
50 changes: 24 additions & 26 deletions lib/futuristic.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

/// A widget that makes it easy to execute a [Future] from a StatelessWidget.
class Futuristic<T> extends StatefulWidget {
Expand All @@ -14,51 +13,50 @@ class Futuristic<T> extends StatefulWidget {
/// Widget to display before the [Future] starts executing.
/// Call [VoidCallback] to start executing the [Future].
/// If not null, [autoStart] should be false.
final Widget Function(BuildContext, VoidCallback) initialBuilder;
final Widget Function(BuildContext, VoidCallback)? initialBuilder;

/// Widget to display while the [Future] is executing.
/// If null, a [CircularProgressIndicator] will be displayed.
final WidgetBuilder busyBuilder;
final WidgetBuilder? busyBuilder;

/// Widget to display when the [Future] has completed with an error.
/// If null, [initialBuilder] will be displayed again.
/// The [Object] is the [Error] or [Exception] returned by the [Future].
/// Call [VoidCallback] to start executing the [Future] again.
final Widget Function(BuildContext, Object, VoidCallback) errorBuilder;
final Widget Function(BuildContext, Object, VoidCallback)? errorBuilder;

/// Widget to display when the [Future] has completed successfully.
/// If null, [initialBuilder] will be displayed again.
final Widget Function(BuildContext, T) dataBuilder;
final Widget Function(BuildContext, T?)? dataBuilder;

/// Callback to invoke when the [Future] has completed successfully.
/// Will only be invoked once per [Future] execution.
final ValueChanged<T> onData;
final ValueChanged<T>? onData;

/// Callback to invoke when the [Future] has completed with an error.
/// Will only be invoked once per [Future] execution.
/// Call [VoidCallback] to start executing the [Future] again.
final Function(Object, VoidCallback) onError;
final Function(Object, VoidCallback)? onError;

const Futuristic({
Key key,
@required this.futureBuilder,
Key? key,
required this.futureBuilder,
this.autoStart = false,
this.initialBuilder,
this.busyBuilder,
this.errorBuilder,
this.dataBuilder,
this.onData,
this.onError
}) : assert(futureBuilder != null),
assert(autoStart ^ (initialBuilder != null)),
}) : assert(autoStart ^ (initialBuilder != null)),
super(key: key);

@override
_FuturisticState<T> createState() => _FuturisticState<T>();
State<Futuristic<T>> createState() => _FuturisticState<T>();
}

class _FuturisticState<T> extends State<Futuristic<T>> {
Future<T> _future;
Future<T>? _future;

@override
void initState() {
Expand All @@ -72,15 +70,15 @@ class _FuturisticState<T> extends State<Futuristic<T>> {
Widget build(BuildContext context) {
return FutureBuilder<T>(
future: _future,
builder: (_context, snapshot) {
builder: (innerContext, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return _handleInitial(_context);
return _handleInitial(innerContext);
case ConnectionState.waiting:
case ConnectionState.active:
return _handleBusy(_context);
return _handleBusy(innerContext);
case ConnectionState.done:
return _handleSnapshot(_context, snapshot);
return _handleSnapshot(innerContext, snapshot);
default:
return _defaultWidget();
}
Expand All @@ -90,28 +88,28 @@ class _FuturisticState<T> extends State<Futuristic<T>> {

Widget _handleInitial(BuildContext context) {
if (widget.initialBuilder != null) {
return widget.initialBuilder(context, _execute);
return widget.initialBuilder!(context, _execute);
}
return _defaultWidget();
}

Widget _handleSnapshot(BuildContext context, AsyncSnapshot<T> snapshot) {
if (snapshot.hasError) {
return _handleError(context, snapshot.error);
return _handleError(context, snapshot.error!);
}
return _handleData(context, snapshot.data);
}

Widget _handleError(BuildContext context, Object error) {
if (widget.errorBuilder != null) {
return widget.errorBuilder(context, error, _execute);
return widget.errorBuilder!(context, error, _execute);
}
return _handleInitial(context);
}

Widget _handleData(BuildContext context, T data) {
Widget _handleData(BuildContext context, T? data) {
if (widget.dataBuilder != null) {
return widget.dataBuilder(context, data);
return widget.dataBuilder!(context, data);
}
return _handleInitial(context);
}
Expand All @@ -120,25 +118,25 @@ class _FuturisticState<T> extends State<Futuristic<T>> {
if (widget.busyBuilder == null) {
return _defaultBusyWidget();
}
return widget.busyBuilder(context);
return widget.busyBuilder!(context);
}

void _execute() {
setState(() {
_future = widget.futureBuilder();
_future.then(_onData).catchError(_onError);
_future?.then(_onData).catchError(_onError);
});
}

void _onData(T data) async {
if (widget.onData != null && _isActive()) {
widget.onData(data);
widget.onData!(data);
}
}

void _onError(Object e) async {
if (widget.onError != null && _isActive()) {
widget.onError(e, _execute);
widget.onError!(e, _execute);
}
}

Expand Down
Loading

0 comments on commit 3b556d1

Please sign in to comment.