showRefusal function
Reports a failed action, offering the store when a purchase would fix it.
The offer is made from the server's stable error code and nothing else. A refusal a purchase cannot lift — a pending purchase, a rate limit, a bug — gets the message alone, because inviting someone to pay for something buying cannot resolve reads as being charged for a defect.
The action is also withheld when this build sells nothing, so a game with no storefront never advertises one.
Implementation
void showRefusal(BuildContext context, WidgetRef ref, Object error) {
final code = error is EngineException ? error.code : null;
final upgradeable =
isUpgradeableRefusal(code) && ref.read(storeAvailableProvider);
// Resolved now rather than on tap. The snack bar outlives whatever showed it
// -- a picker the player closes, a join screen that has already gone home --
// and a late tap would otherwise look the router up from an unmounted context.
final router = GoRouter.maybeOf(context);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(humanize(error)),
action: upgradeable
? SnackBarAction(
label: 'See options',
onPressed: () =>
(router ?? GoRouter.of(context)).goNamed('store'),
)
: null,
),
);
}