Skip to content

Commit a34c80f

Browse files
authored
Merge pull request #144 from MostroP2P/improve-cancel
fix: resolve cancel button loading state and improve cancel dialog UX
2 parents e68975b + a08b82b commit a34c80f

File tree

5 files changed

+57
-6
lines changed

5 files changed

+57
-6
lines changed

lib/features/trades/screens/trade_detail_screen.dart

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -284,33 +284,40 @@ class TradeDetailScreen extends ConsumerWidget {
284284
cancelMessage = S.of(context)!.areYouSureCancel;
285285
}
286286

287+
final buttonController = MostroReactiveButtonController();
287288
widgets.add(_buildNostrButton(
288289
S.of(context)!.cancel.toUpperCase(),
289290
action: action,
290291
backgroundColor: AppTheme.red1,
291-
onPressed: () {
292-
showDialog(
292+
controller: buttonController,
293+
onPressed: () async {
294+
final result = await showDialog<bool>(
293295
context: context,
294296
builder: (context) => AlertDialog(
295297
title: Text(S.of(context)!.cancelTradeDialogTitle),
296298
content: Text(cancelMessage),
297299
actions: [
298300
TextButton(
299-
onPressed: () => context.pop(),
300-
child: Text(S.of(context)!.cancel),
301+
onPressed: () => context.pop(false),
302+
child: Text(S.of(context)!.no),
301303
),
302304
ElevatedButton(
303305
onPressed: () {
304-
context.pop();
306+
context.pop(true);
305307
ref
306308
.read(orderNotifierProvider(orderId).notifier)
307309
.cancelOrder();
308310
},
309-
child: Text(S.of(context)!.confirm),
311+
child: Text(S.of(context)!.yes),
310312
),
311313
],
312314
),
313315
);
316+
317+
// Reset loading state if dialog was cancelled
318+
if (result != true) {
319+
buttonController.resetLoading();
320+
}
314321
},
315322
));
316323
break;
@@ -490,8 +497,11 @@ class TradeDetailScreen extends ConsumerWidget {
490497
required actions.Action action,
491498
required VoidCallback? onPressed,
492499
Color? backgroundColor,
500+
Key? key,
501+
MostroReactiveButtonController? controller,
493502
}) {
494503
return MostroReactiveButton(
504+
key: key,
495505
label: label,
496506
buttonStyle: ButtonStyleType.raised,
497507
orderId: orderId,
@@ -500,6 +510,7 @@ class TradeDetailScreen extends ConsumerWidget {
500510
onPressed: onPressed ?? () {}, // Provide empty function when null
501511
showSuccessIndicator: true,
502512
timeout: const Duration(seconds: 30),
513+
controller: controller,
503514
);
504515
}
505516

lib/l10n/intl_en.arb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@
203203
"cooperativeCancelMessage": "If you confirm, you will start a cooperative cancellation with your counterparty.",
204204
"acceptCancelMessage": "If you confirm, you will accept the cooperative cancellation initiated by your counterparty.",
205205
"confirm": "Confirm",
206+
"yes": "Yes",
207+
"no": "No",
206208
"buy": "BUY",
207209
"sell": "SELL",
208210
"buying": "BUYING",

lib/l10n/intl_es.arb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@
164164
"cooperativeCancelMessage": "Si confirmas, iniciarás una cancelación cooperativa con tu contraparte.",
165165
"acceptCancelMessage": "Si confirmas, aceptarás la cancelación cooperativa iniciada por tu contraparte.",
166166
"confirm": "Confirmar",
167+
"yes": "Sí",
168+
"no": "No",
167169
"buy": "COMPRAR",
168170
"sell": "VENDER",
169171
"buying": "COMPRANDO",

lib/l10n/intl_it.arb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@
164164
"cooperativeCancelMessage": "Se confermi, inizierai un annullamento cooperativo con la tua controparte.",
165165
"acceptCancelMessage": "Se confermi, accetterai l'annullamento cooperativo iniziato dalla tua controparte.",
166166
"confirm": "Conferma",
167+
"yes": "Sì",
168+
"no": "No",
167169
"buy": "COMPRA",
168170
"sell": "VENDI",
169171
"buying": "COMPRANDO",

lib/shared/widgets/mostro_reactive_button.dart

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,23 @@ import 'package:mostro_mobile/core/app_theme.dart';
88

99
enum ButtonStyleType { raised, outlined, text }
1010

11+
/// Controller for managing MostroReactiveButton state externally
12+
class MostroReactiveButtonController {
13+
_MostroReactiveButtonState? _state;
14+
15+
void _attach(_MostroReactiveButtonState state) {
16+
_state = state;
17+
}
18+
19+
void _detach() {
20+
_state = null;
21+
}
22+
23+
void resetLoading() {
24+
_state?.resetLoading();
25+
}
26+
}
27+
1128
/// A button specially designed for reactive operations that shows loading state
1229
/// and handles the unique event-based nature of the mostro protocol.
1330
class MostroReactiveButton extends ConsumerStatefulWidget {
@@ -21,6 +38,7 @@ class MostroReactiveButton extends ConsumerStatefulWidget {
2138
final bool showSuccessIndicator;
2239

2340
final Color? backgroundColor;
41+
final MostroReactiveButtonController? controller;
2442

2543
const MostroReactiveButton({
2644
super.key,
@@ -32,6 +50,7 @@ class MostroReactiveButton extends ConsumerStatefulWidget {
3250
this.timeout = const Duration(seconds: 30),
3351
this.showSuccessIndicator = false,
3452
this.backgroundColor,
53+
this.controller,
3554
});
3655

3756
@override
@@ -45,12 +64,27 @@ class _MostroReactiveButtonState extends ConsumerState<MostroReactiveButton> {
4564
Timer? _timeoutTimer;
4665
dynamic _lastSeenAction;
4766

67+
@override
68+
void initState() {
69+
super.initState();
70+
widget.controller?._attach(this);
71+
}
72+
4873
@override
4974
void dispose() {
75+
widget.controller?._detach();
5076
_timeoutTimer?.cancel();
5177
super.dispose();
5278
}
5379

80+
void resetLoading() {
81+
setState(() {
82+
_loading = false;
83+
_showSuccess = false;
84+
});
85+
_timeoutTimer?.cancel();
86+
}
87+
5488
void _startOperation() {
5589
setState(() {
5690
_loading = true;

0 commit comments

Comments
 (0)