Skip to content

Commit 1f0fcf0

Browse files
authored
Merge pull request #128 from MostroP2P/chebizarro/issue72
Fixes: Add confirmation message before starting cooperative cancellation
2 parents 57dfcfd + 1e82193 commit 1f0fcf0

File tree

2 files changed

+60
-25
lines changed

2 files changed

+60
-25
lines changed

lib/features/order/models/order_state.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,14 +221,22 @@ class OrderState {
221221
Action.buyerTookOrder: [
222222
Action.cancel,
223223
Action.dispute,
224+
Action.sendDm,
224225
],
225226
Action.holdInvoicePaymentAccepted: [
226227
Action.cancel,
227228
Action.dispute,
229+
Action.sendDm,
228230
],
229231
Action.holdInvoicePaymentSettled: [
230232
Action.cancel,
231233
Action.dispute,
234+
Action.sendDm,
235+
],
236+
Action.cooperativeCancelInitiatedByPeer: [
237+
Action.cancel,
238+
Action.dispute,
239+
Action.sendDm,
232240
],
233241
},
234242
Status.fiatSent: {
@@ -287,21 +295,30 @@ class OrderState {
287295
Action.fiatSent,
288296
Action.cancel,
289297
Action.dispute,
298+
Action.sendDm,
290299
],
291300
Action.holdInvoicePaymentSettled: [
292301
Action.fiatSent,
293302
Action.cancel,
294303
Action.dispute,
304+
Action.sendDm,
295305
],
296306
Action.buyerTookOrder: [
297307
Action.cancel,
298308
Action.dispute,
309+
Action.sendDm,
310+
],
311+
Action.cooperativeCancelInitiatedByPeer: [
312+
Action.cancel,
313+
Action.dispute,
314+
Action.sendDm,
299315
],
300316
},
301317
Status.fiatSent: {
302318
Action.fiatSentOk: [
303319
Action.cancel,
304320
Action.dispute,
321+
Action.sendDm,
305322
],
306323
},
307324
Status.success: {

lib/features/trades/screens/trade_detail_screen.dart

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ class TradeDetailScreen extends ConsumerWidget {
5353
// Detailed info: includes the last Mostro message action text
5454
MostroMessageDetail(orderId: orderId),
5555
const SizedBox(height: 24),
56-
_buildCountDownTime(orderPayload.expiresAt),
56+
_buildCountDownTime(orderPayload.expiresAt != null
57+
? orderPayload.expiresAt! * 1000
58+
: null),
5759
const SizedBox(height: 36),
5860
Wrap(
5961
alignment: WrapAlignment.center,
@@ -104,10 +106,9 @@ class TradeDetailScreen extends ConsumerWidget {
104106
final method = tradeState.order!.paymentMethod;
105107
final timestamp = formatDateTime(
106108
tradeState.order!.createdAt != null && tradeState.order!.createdAt! > 0
107-
? DateTime.fromMillisecondsSinceEpoch(tradeState.order!.createdAt!)
108-
: DateTime.fromMillisecondsSinceEpoch(
109-
tradeState.order!.createdAt ?? 0,
110-
),
109+
? DateTime.fromMillisecondsSinceEpoch(
110+
tradeState.order!.createdAt! * 1000)
111+
: session.startTime,
111112
);
112113
return CustomCard(
113114
padding: const EdgeInsets.all(16),
@@ -223,24 +224,49 @@ class TradeDetailScreen extends ConsumerWidget {
223224
// FSM-driven action mapping: ensure all actions are handled
224225
switch (action) {
225226
case actions.Action.cancel:
226-
String buttonText;
227-
Color buttonColor;
227+
String cancelMessage;
228228

229229
if (tradeState.status == Status.active ||
230230
tradeState.status == Status.fiatSent) {
231-
buttonText = 'COOPERATIVE CANCEL';
232-
buttonColor = AppTheme.red1;
231+
if (tradeState.action == actions.Action.cooperativeCancelInitiatedByPeer) {
232+
cancelMessage =
233+
'If you confirm, you will accept the cooperative cancellation initiated by your counterparty.';
234+
} else {
235+
cancelMessage =
236+
'If you confirm, you will start a cooperative cancellation with your counterparty.';
237+
}
233238
} else {
234-
buttonText = 'CANCEL';
235-
buttonColor = AppTheme.red1;
239+
cancelMessage = 'Are you sure you want to cancel this trade?';
236240
}
237241

238242
widgets.add(_buildNostrButton(
239-
buttonText,
243+
'CANCEL',
240244
action: action,
241-
backgroundColor: buttonColor,
242-
onPressed: () =>
243-
ref.read(orderNotifierProvider(orderId).notifier).cancelOrder(),
245+
backgroundColor: AppTheme.red1,
246+
onPressed: () {
247+
showDialog(
248+
context: context,
249+
builder: (context) => AlertDialog(
250+
title: const Text('Cancel Trade'),
251+
content: Text(cancelMessage),
252+
actions: [
253+
TextButton(
254+
onPressed: () => context.pop(),
255+
child: const Text('Cancel'),
256+
),
257+
ElevatedButton(
258+
onPressed: () {
259+
context.pop();
260+
ref
261+
.read(orderNotifierProvider(orderId).notifier)
262+
.cancelOrder();
263+
},
264+
child: const Text('Confirm'),
265+
),
266+
],
267+
),
268+
);
269+
},
244270
));
245271
break;
246272

@@ -386,15 +412,11 @@ class TradeDetailScreen extends ConsumerWidget {
386412
));
387413
break;
388414

389-
case actions.Action.holdInvoicePaymentSettled:
390-
case actions.Action.holdInvoicePaymentAccepted:
415+
case actions.Action.sendDm:
391416
widgets.add(_buildContactButton(context));
392417
break;
393418

394419
case actions.Action.holdInvoicePaymentCanceled:
395-
// These are system actions, not user actions, so no button needed
396-
break;
397-
398420
case actions.Action.buyerInvoiceAccepted:
399421
case actions.Action.waitingSellerToPay:
400422
case actions.Action.waitingBuyerInvoice:
@@ -407,15 +429,11 @@ class TradeDetailScreen extends ConsumerWidget {
407429
case actions.Action.adminTookDispute:
408430
case actions.Action.paymentFailed:
409431
case actions.Action.invoiceUpdated:
410-
case actions.Action.sendDm:
411432
case actions.Action.tradePubkey:
412433
case actions.Action.cantDo:
413434
case actions.Action.released:
414-
// Not user-facing or not relevant as a button
415435
break;
416-
417436
default:
418-
// Optionally handle unknown or unimplemented actions
419437
break;
420438
}
421439
}
@@ -457,7 +475,7 @@ class TradeDetailScreen extends ConsumerWidget {
457475
/// CLOSE
458476
Widget _buildCloseButton(BuildContext context) {
459477
return OutlinedButton(
460-
onPressed: () => context.pop(),
478+
onPressed: () => context.go('/order_book'),
461479
style: AppTheme.theme.outlinedButtonTheme.style,
462480
child: const Text('CLOSE'),
463481
);

0 commit comments

Comments
 (0)