mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-25 06:19:22 +00:00
114 lines
2.7 KiB
Dart
114 lines
2.7 KiB
Dart
import 'package:comunic/ui/widgets/safe_state.dart';
|
|
import 'package:comunic/utils/intl_utils.dart';
|
|
import 'package:comunic/utils/ui_utils.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
/// Widget that can be used to easily implement fetch of remote ressources
|
|
///
|
|
/// @author Pierre Hubert
|
|
|
|
class AsyncScreenWidget extends StatefulWidget {
|
|
/// Reload function
|
|
///
|
|
/// Can be an asynchronous function that takes no arguments and throw an
|
|
/// [Exception] in case of failure
|
|
///
|
|
/// You do not need to call [State.setState] on this function, it is
|
|
/// automatically done by this widget
|
|
final Future<void> Function() onReload;
|
|
|
|
/// Build function
|
|
///
|
|
/// This function will be called whenever [isReady] becomes true
|
|
final Widget Function() onBuild;
|
|
|
|
/// Error message that will be shown in case of error
|
|
final String errorMessage;
|
|
|
|
/// Specify whether old data can be kept or not while updating this widget
|
|
final bool showOldDataWhileUpdating;
|
|
|
|
/// Widget to use while we are refreshing
|
|
///
|
|
/// This widget is optional
|
|
final Widget? loadingWidget;
|
|
|
|
/// Widget to use in case of error
|
|
///
|
|
/// This widget is optional
|
|
final Widget? errorWidget;
|
|
|
|
const AsyncScreenWidget({
|
|
Key? key,
|
|
required this.onReload,
|
|
required this.onBuild,
|
|
required this.errorMessage,
|
|
this.showOldDataWhileUpdating = false,
|
|
this.loadingWidget,
|
|
this.errorWidget,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
AsyncScreenWidgetState createState() => AsyncScreenWidgetState();
|
|
}
|
|
|
|
class AsyncScreenWidgetState extends SafeState<AsyncScreenWidget> {
|
|
bool error = false;
|
|
bool ready = false;
|
|
bool didFirstLoad = false;
|
|
|
|
@override
|
|
void initState() {
|
|
refresh();
|
|
super.initState();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// In case of error
|
|
if (error)
|
|
return widget.errorWidget ??
|
|
buildErrorCard(widget.errorMessage, actions: [
|
|
MaterialButton(
|
|
textColor: Colors.white,
|
|
onPressed: () => refresh(),
|
|
child: Text(tr("Try again")!.toUpperCase()),
|
|
)
|
|
]);
|
|
|
|
// Show loading states
|
|
if (!ready) return widget.loadingWidget ?? buildCenteredProgressBar();
|
|
|
|
// The widget is ready, show it
|
|
return RefreshIndicator(
|
|
child: widget.onBuild(),
|
|
onRefresh: () => refresh(),
|
|
);
|
|
}
|
|
|
|
/// Refresh this screen
|
|
Future<void> refresh() async {
|
|
try {
|
|
setState(() {
|
|
error = false;
|
|
ready = widget.showOldDataWhileUpdating && didFirstLoad;
|
|
});
|
|
|
|
// Call parent method
|
|
await widget.onReload();
|
|
|
|
setState(() {
|
|
ready = true;
|
|
didFirstLoad = true;
|
|
});
|
|
} catch (e, stack) {
|
|
print(e);
|
|
print(stack);
|
|
|
|
setState(() {
|
|
error = true;
|
|
});
|
|
}
|
|
}
|
|
}
|