11import 'package:flutter/material.dart' ;
22import 'package:yaru/yaru.dart' ;
33
4+ import '../../extensions/build_context_x.dart' ;
45import '../../l10n/l10n.dart' ;
6+ import 'progress.dart' ;
57import 'theme.dart' ;
68import 'ui_constants.dart' ;
79
8- class ConfirmationDialog extends StatelessWidget {
10+ class ConfirmationDialog < T > extends StatefulWidget {
911 const ConfirmationDialog ({
1012 super .key,
1113 this .onConfirm,
@@ -20,67 +22,180 @@ class ConfirmationDialog extends StatelessWidget {
2022 this .cancelLabel,
2123 this .confirmEnabled = true ,
2224 this .contentPadding,
25+ this .titlePadding,
2326 });
24-
25- final dynamic Function ()? onConfirm;
26- final bool confirmEnabled;
27- final dynamic Function ()? onCancel;
27+ final Future <T > Function ()? onConfirm;
28+ final Future <T > Function ()? onCancel;
2829 final List <Widget >? additionalActions;
2930 final Widget ? title;
3031 final Widget ? content;
3132 final bool showCancel;
3233 final bool showCloseIcon;
3334 final bool scrollable;
34- final String ? confirmLabel, cancelLabel;
35+ final String ? confirmLabel;
36+ final String ? cancelLabel;
3537 final EdgeInsetsGeometry ? contentPadding;
38+ final bool confirmEnabled;
39+ final EdgeInsetsGeometry ? titlePadding;
40+
41+ static Future <T ?> show <T >({
42+ required BuildContext context,
43+ required Future <T > Function () onConfirm,
44+ Widget ? title,
45+ Widget ? content,
46+ String ? confirmLabel,
47+ String ? cancelLabel,
48+ bool barrierDismissible = false ,
49+ bool confirmEnabled = true ,
50+ bool scrollable = false ,
51+ List <Widget >? additionalActions,
52+ EdgeInsetsGeometry ? contentPadding,
53+ Future <T > Function ()? onCancel,
54+ bool showCancel = true ,
55+ }) => showDialog (
56+ context: context,
57+ barrierDismissible: barrierDismissible,
58+ builder: (context) => ConfirmationDialog <T >(
59+ title: title,
60+ content: content,
61+ onConfirm: onConfirm,
62+ confirmLabel: confirmLabel,
63+ cancelLabel: cancelLabel,
64+ showCloseIcon: barrierDismissible,
65+ confirmEnabled: confirmEnabled,
66+ scrollable: scrollable,
67+ additionalActions: additionalActions,
68+ contentPadding: contentPadding,
69+ onCancel: onCancel,
70+ showCancel: showCancel,
71+ ),
72+ );
73+
74+ @override
75+ State <ConfirmationDialog <T >> createState () => _ConfirmationDialogState ();
76+ }
77+
78+ class _ConfirmationDialogState <T > extends State <ConfirmationDialog <T >> {
79+ bool _loading = false ;
80+ String ? _error;
3681
3782 @override
3883 Widget build (BuildContext context) {
3984 final l10n = context.l10n;
4085 return AlertDialog (
86+ titlePadding: widget.titlePadding ?? EdgeInsets .zero,
4187 title: YaruDialogTitleBar (
42- title: title,
4388 backgroundColor: Colors .transparent,
89+ title: widget.title,
90+ isClosable: widget.showCloseIcon,
4491 border: BorderSide .none,
45- isClosable: showCloseIcon,
4692 ),
47- scrollable: scrollable,
48- titlePadding: EdgeInsets .zero,
49- content: content,
50- contentPadding: contentPadding,
93+ scrollable: widget.scrollable,
94+ content: _error != null
95+ ? Padding (
96+ padding: const EdgeInsets .all (8 ),
97+ child: Text (
98+ _error! ,
99+ style: context.textTheme.bodyLarge! .copyWith (
100+ color: context.colorScheme.error,
101+ ),
102+ textAlign: TextAlign .center,
103+ ),
104+ )
105+ : _loading
106+ ? const SizedBox .square (
107+ dimension: 60 ,
108+ child: Center (
109+ child: SizedBox .square (dimension: 24 , child: Progress ()),
110+ ),
111+ )
112+ : widget.content,
113+ contentPadding: widget.contentPadding,
51114 actionsAlignment: MainAxisAlignment .start,
52115 actionsOverflowAlignment: OverflowBarAlignment .center,
53116 actionsPadding: const EdgeInsets .all (kMediumSpace),
54117 actions: [
55118 Row (
56119 children: space (
57120 expandAll: true ,
58- widthGap: kMediumSpace,
59- children: [
60- ...? additionalActions,
61- if (showCancel)
62- OutlinedButton (
63- onPressed: () {
64- onCancel? .call ();
65- if (context.mounted && Navigator .of (context).canPop ()) {
66- Navigator .of (context).pop ();
67- }
68- },
69- child: Text (cancelLabel ?? l10n.cancel),
70- ),
71- ElevatedButton (
72- onPressed: confirmEnabled
73- ? () {
74- onConfirm? .call ();
75-
121+ widthGap: 16 ,
122+ children: _error != null
123+ ? [
124+ OutlinedButton (
125+ onPressed: () {
76126 if (context.mounted && Navigator .of (context).canPop ()) {
77127 Navigator .of (context).pop ();
78128 }
79- }
80- : null ,
81- child: Text (confirmLabel ?? l10n.ok),
82- ),
83- ],
129+ },
130+ child: Text (l10n.ok),
131+ ),
132+ ]
133+ : [
134+ if (widget.showCancel)
135+ OutlinedButton (
136+ onPressed: _loading
137+ ? null
138+ : () {
139+ if (widget.onCancel is Future <T > Function ()) {
140+ setState (() => _loading = true );
141+ widget.onCancel !()
142+ .then ((_) {
143+ if (context.mounted &&
144+ Navigator .of (context).canPop ()) {
145+ Navigator .of (context).pop ();
146+ }
147+ })
148+ .catchError ((error) {
149+ setState (() {
150+ _loading = false ;
151+ _error = error.toString ();
152+ });
153+ });
154+ } else {
155+ widget.onCancel? .call ();
156+ if (context.mounted &&
157+ Navigator .of (context).canPop ()) {
158+ Navigator .of (context).pop ();
159+ }
160+ }
161+ },
162+ child: Text (widget.cancelLabel ?? l10n.cancel),
163+ ),
164+ ...? widget.additionalActions,
165+ ElevatedButton (
166+ onPressed: _loading
167+ ? null
168+ : widget.confirmEnabled
169+ ? () {
170+ if (widget.onConfirm != null ) {
171+ if (widget.onConfirm is Future <T > Function ()) {
172+ setState (() => _loading = true );
173+ widget.onConfirm !()
174+ .then ((_) {
175+ if (context.mounted &&
176+ Navigator .of (context).canPop ()) {
177+ Navigator .of (context).pop ();
178+ }
179+ })
180+ .catchError ((error) {
181+ setState (() {
182+ _loading = false ;
183+ _error = error.toString ();
184+ });
185+ });
186+ } else {
187+ widget.onConfirm !();
188+ setState (() => _loading = false );
189+ }
190+ } else if (context.mounted &&
191+ Navigator .of (context).canPop ()) {
192+ Navigator .of (context).pop ();
193+ }
194+ }
195+ : null ,
196+ child: Text (widget.confirmLabel ?? l10n.ok),
197+ ),
198+ ],
84199 ),
85200 ),
86201 ],
0 commit comments