ente/lib/ui/common/progress_dialog.dart

292 lines
8.2 KiB
Dart
Raw Normal View History

2023-12-21 07:34:06 +00:00
import "dart:async";
2021-03-31 08:24:50 +00:00
import 'package:flutter/material.dart';
2022-07-03 10:09:01 +00:00
enum ProgressDialogType { normal, download }
2021-03-31 08:24:50 +00:00
String _dialogMessage = "Loading...";
double _progress = 0.0, _maxProgress = 100.0;
Widget? _customBody;
2021-03-31 08:24:50 +00:00
TextAlign _textAlign = TextAlign.left;
Alignment _progressWidgetAlignment = Alignment.centerLeft;
TextDirection _direction = TextDirection.ltr;
bool _isShowing = false;
BuildContext? _context, _dismissingContext;
ProgressDialogType? _progressDialogType;
2021-03-31 08:24:50 +00:00
bool _barrierDismissible = true, _showLogs = false;
Color? _barrierColor;
2021-03-31 08:24:50 +00:00
2022-07-04 06:02:17 +00:00
TextStyle _progressTextStyle = const TextStyle(
2022-06-11 08:23:52 +00:00
color: Colors.black,
fontSize: 12.0,
fontWeight: FontWeight.w400,
),
2022-07-04 06:02:17 +00:00
_messageStyle = const TextStyle(
2022-06-11 08:23:52 +00:00
color: Colors.black,
fontSize: 18.0,
fontWeight: FontWeight.w600,
);
2021-03-31 08:24:50 +00:00
double _dialogElevation = 8.0, _borderRadius = 8.0;
Color _backgroundColor = Colors.white;
Curve _insetAnimCurve = Curves.easeInOut;
EdgeInsets _dialogPadding = const EdgeInsets.all(8.0);
Widget _progressWidget = Image.asset(
'assets/double_ring_loading_io.gif',
package: 'progress_dialog',
);
class ProgressDialog {
_Body? _dialog;
2021-03-31 08:24:50 +00:00
ProgressDialog(
BuildContext context, {
ProgressDialogType? type,
bool? isDismissible,
bool? showLogs,
TextDirection? textDirection,
Widget? customBody,
Color? barrierColor,
2021-03-31 08:24:50 +00:00
}) {
_context = context;
2022-07-03 10:09:01 +00:00
_progressDialogType = type ?? ProgressDialogType.normal;
2021-03-31 08:24:50 +00:00
_barrierDismissible = isDismissible ?? true;
_showLogs = showLogs ?? false;
2022-07-12 06:30:02 +00:00
_customBody = customBody;
2021-03-31 08:24:50 +00:00
_direction = textDirection ?? TextDirection.ltr;
_barrierColor = barrierColor ?? barrierColor;
}
2022-06-11 08:23:52 +00:00
void style({
Widget? child,
double? progress,
double? maxProgress,
String? message,
Widget? progressWidget,
Color? backgroundColor,
TextStyle? progressTextStyle,
TextStyle? messageTextStyle,
double? elevation,
TextAlign? textAlign,
double? borderRadius,
Curve? insetAnimCurve,
EdgeInsets? padding,
Alignment? progressWidgetAlignment,
2022-06-11 08:23:52 +00:00
}) {
2021-03-31 08:24:50 +00:00
if (_isShowing) return;
2022-07-03 10:09:01 +00:00
if (_progressDialogType == ProgressDialogType.download) {
2021-03-31 08:24:50 +00:00
_progress = progress ?? _progress;
}
_dialogMessage = message ?? _dialogMessage;
_maxProgress = maxProgress ?? _maxProgress;
_progressWidget = progressWidget ?? _progressWidget;
_backgroundColor = backgroundColor ?? _backgroundColor;
_messageStyle = messageTextStyle ?? _messageStyle;
_progressTextStyle = progressTextStyle ?? _progressTextStyle;
_dialogElevation = elevation ?? _dialogElevation;
_borderRadius = borderRadius ?? _borderRadius;
_insetAnimCurve = insetAnimCurve ?? _insetAnimCurve;
_textAlign = textAlign ?? _textAlign;
_progressWidget = child ?? _progressWidget;
_dialogPadding = padding ?? _dialogPadding;
2022-07-03 09:49:33 +00:00
_progressWidgetAlignment =
progressWidgetAlignment ?? _progressWidgetAlignment;
2021-03-31 08:24:50 +00:00
}
2022-06-11 08:23:52 +00:00
void update({
double? progress,
double? maxProgress,
String? message,
Widget? progressWidget,
TextStyle? progressTextStyle,
TextStyle? messageTextStyle,
2022-06-11 08:23:52 +00:00
}) {
2022-07-03 10:09:01 +00:00
if (_progressDialogType == ProgressDialogType.download) {
2021-03-31 08:24:50 +00:00
_progress = progress ?? _progress;
}
_dialogMessage = message ?? _dialogMessage;
_maxProgress = maxProgress ?? _maxProgress;
_progressWidget = progressWidget ?? _progressWidget;
_messageStyle = messageTextStyle ?? _messageStyle;
_progressTextStyle = progressTextStyle ?? _progressTextStyle;
if (_isShowing) _dialog!.update();
2021-03-31 08:24:50 +00:00
}
bool isShowing() {
return _isShowing;
}
Future<bool> hide() async {
try {
if (_isShowing) {
_isShowing = false;
if (_dismissingContext != null) {
Navigator.of(_dismissingContext!).pop();
}
2021-03-31 08:24:50 +00:00
if (_showLogs) debugPrint('ProgressDialog dismissed');
return Future.value(true);
} else {
if (_showLogs) debugPrint('ProgressDialog already dismissed');
return Future.value(false);
}
} catch (err) {
debugPrint('Seems there is an issue hiding dialog');
debugPrint(err.toString());
return Future.value(false);
}
}
Future<bool> show() async {
try {
if (!_isShowing) {
2022-07-03 06:49:00 +00:00
_dialog = _Body();
2023-12-21 07:34:06 +00:00
unawaited(
showDialog<dynamic>(
context: _context!,
barrierDismissible: _barrierDismissible,
barrierColor: _barrierColor,
builder: (BuildContext context) {
_dismissingContext = context;
return WillPopScope(
onWillPop: () async => _barrierDismissible,
child: Dialog(
backgroundColor: _backgroundColor,
insetAnimationCurve: _insetAnimCurve,
insetAnimationDuration: const Duration(milliseconds: 100),
elevation: _dialogElevation,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(_borderRadius)),
),
child: _dialog,
2022-06-11 08:23:52 +00:00
),
2023-12-21 07:34:06 +00:00
);
},
),
2021-03-31 08:24:50 +00:00
);
// Delaying the function for 200 milliseconds
// [Default transitionDuration of DialogRoute]
2022-07-04 06:02:17 +00:00
await Future.delayed(const Duration(milliseconds: 200));
2021-03-31 08:24:50 +00:00
if (_showLogs) debugPrint('ProgressDialog shown');
_isShowing = true;
return true;
} else {
if (_showLogs) debugPrint("ProgressDialog already shown/showing");
return false;
}
} catch (err) {
_isShowing = false;
debugPrint('Exception while showing the dialog');
debugPrint(err.toString());
return false;
}
}
}
// ignore: must_be_immutable
class _Body extends StatefulWidget {
final _BodyState _dialog = _BodyState();
2021-03-31 08:24:50 +00:00
update() {
_dialog.update();
}
@override
State<StatefulWidget> createState() {
return _dialog;
}
}
class _BodyState extends State<_Body> {
update() {
setState(() {});
}
@override
void dispose() {
_isShowing = false;
if (_showLogs) debugPrint('ProgressDialog dismissed by back button');
super.dispose();
}
@override
Widget build(BuildContext context) {
final loader = Align(
alignment: _progressWidgetAlignment,
child: SizedBox(
width: 60.0,
height: 60.0,
child: _progressWidget,
),
);
final text = Expanded(
2022-07-03 10:09:01 +00:00
child: _progressDialogType == ProgressDialogType.normal
2021-03-31 08:24:50 +00:00
? Text(
_dialogMessage,
textAlign: _textAlign,
style: _messageStyle,
textDirection: _direction,
)
: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
2022-07-04 06:02:17 +00:00
const SizedBox(height: 8.0),
2021-03-31 08:24:50 +00:00
Row(
children: <Widget>[
Expanded(
2022-06-11 08:23:52 +00:00
child: Text(
_dialogMessage,
style: _messageStyle,
textDirection: _direction,
),
),
2021-03-31 08:24:50 +00:00
],
),
2022-07-04 06:02:17 +00:00
const SizedBox(height: 4.0),
2021-03-31 08:24:50 +00:00
Align(
alignment: Alignment.bottomRight,
child: Text(
"$_progress/$_maxProgress",
style: _progressTextStyle,
textDirection: _direction,
),
),
],
),
),
);
return _customBody ??
Container(
padding: _dialogPadding,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
// row body
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(width: 8.0),
_direction == TextDirection.ltr ? loader : text,
const SizedBox(width: 8.0),
_direction == TextDirection.rtl ? loader : text,
2023-08-19 11:39:56 +00:00
const SizedBox(width: 8.0),
2021-03-31 08:24:50 +00:00
],
),
],
),
);
}
}