fix(shopinbit): show payment-check API errors as a blocking dialog
What changed, and why it matters
This commit changes how payment-check errors are shown to the user in the ShopInBit feature. Previously, a brief warning banner (a 'flush bar') appeared. Now, a blocking dialog box appears that the user must acknowledge before continuing. This is a user-experience and reliability improvement, not a fix for a code vulnerability. It makes it harder for a user to miss an important payment failure message, but it does not change how payments are processed or how errors are generated.
No security action required. Treat as a normal UX/reliability improvement. If reviewing the broader ShopInBit integration, consider auditing how payment-check exceptions are generated and whether the API response is validated before being shown in the dialog, but that is outside the scope of this commit.
Security signals we found
UI change from non-blocking transient notification to blocking modal dialog
Added mounted check after async dialog dismissal
No changes to payment validation, cryptography, network requests, or trust boundaries
Evidence from the diff
In lib/pages/shopinbit/shopinbit_payment_view.dart, the error-handling branch of the payment-check flow replaces an unawaited showFloatingFlushBar call with an awaited showDialog using StackOkDialog. The dialog is modal and root-navigator-aware for desktop. A mounted guard is added after the await. The change is purely presentational: the same exception message is displayed, but now the user must dismiss it and the async flow waits for dismissal.
Changed components
lib/pages/shopinbit/shopinbit_payment_view.dartShopInBit payment-check error UIInspect captured patch +11 / −6
diff --git a/lib/pages/shopinbit/shopinbit_payment_view.dart b/lib/pages/shopinbit/shopinbit_payment_view.dart
index 6ea6d7f..af80536 100644
--- a/lib/pages/shopinbit/shopinbit_payment_view.dart
+++ b/lib/pages/shopinbit/shopinbit_payment_view.dart
@@ -25,6 +25,7 @@ import '../../widgets/desktop/primary_button.dart';
import '../../widgets/desktop/secondary_button.dart';
import '../../widgets/icon_widgets/copy_icon.dart';
import '../../widgets/rounded_white_container.dart';
+import '../../widgets/stack_dialog.dart';
import 'shopinbit_payment_shared.dart';
class ShopInBitPaymentView extends ConsumerStatefulWidget {
@@ -83,7 +84,7 @@ class _ShopInBitPaymentViewState extends ConsumerState<ShopInBitPaymentView> {
_applyPaymentInfo(widget.initialPaymentInfo!);
}
if (widget.model.apiTicketId != 0) {
- // If the pre-load didn't hand us usable payment links, recover them:
+ // If the pre-load didn't hand us usable payment links, recover them:
// GET, then PUT to generate one.
if (_addresses.every((a) => a.isEmpty)) {
unawaited(_recoverPaymentInfo());
@@ -203,13 +204,17 @@ class _ShopInBitPaymentViewState extends ConsumerState<ShopInBitPaymentView> {
);
}
} else {
- unawaited(
- showFloatingFlushBar(
- type: FlushBarType.warning,
- message: resp?.exception?.message ?? "Failed to check payment.",
- context: context,
+ await showDialog<void>(
+ context: context,
+ useRootNavigator: Util.isDesktop,
+ builder: (context) => StackOkDialog(
+ title: "Failed to check payment",
+ maxWidth: Util.isDesktop ? 500 : null,
+ message: resp?.exception?.message,
+ desktopPopRootNavigator: Util.isDesktop,
),
);
+ if (!mounted) return;
}
if (!_isTerminal) {
Why this scored 21/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.