From a9c3489c8e0578469d9ac6c83a67ce3f031c1de4 Mon Sep 17 00:00:00 2001 From: Vadim <44135514+vodemn@users.noreply.github.com> Date: Fri, 8 Aug 2025 13:37:06 +0200 Subject: [PATCH] handle purchase errors --- .../widget_offering_lightmeter_pro.dart | 101 ++++++++++++------ 1 file changed, 68 insertions(+), 33 deletions(-) diff --git a/lib/screens/lightmeter_pro/components/offering/widget_offering_lightmeter_pro.dart b/lib/screens/lightmeter_pro/components/offering/widget_offering_lightmeter_pro.dart index 53e2796..31d02ac 100644 --- a/lib/screens/lightmeter_pro/components/offering/widget_offering_lightmeter_pro.dart +++ b/lib/screens/lightmeter_pro/components/offering/widget_offering_lightmeter_pro.dart @@ -1,5 +1,7 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter/services.dart'; import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/theme.dart'; @@ -30,22 +32,16 @@ class _LightmeterProOfferingState extends State { yearly = products.firstWhereOrNull((p) => p.type == PurchaseType.yearly); lifetime = products.firstWhereOrNull((p) => p.type == PurchaseType.lifetime); selected = monthly ?? lifetime; - }).onError((_, __) { - /// + }).onError((e, __) { + SchedulerBinding.instance.addPostFrameCallback((_) { + _showSnackbar(e.toString()); + }); }).whenComplete(() { _isLoading = false; if (mounted) setState(() {}); }); } - @override - void didChangeDependencies() { - super.didChangeDependencies(); - if (IAPProducts.isPro(context)) { - Navigator.of(context).pop(); - } - } - @override Widget build(BuildContext context) { return Container( @@ -67,38 +63,77 @@ class _LightmeterProOfferingState extends State { crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisSize: MainAxisSize.min, children: [ - AnimatedSwitcher( - duration: Dimens.durationM, - child: _isLoading - ? const SizedBox( - height: 120, - child: Center(child: CircularProgressIndicator()), - ) - : _Products( - monthly: monthly, - yearly: yearly, - lifetime: lifetime, - selected: selected, - onProductSelected: (value) { - setState(() { - selected = value; - }); - }, - ), + Stack( + alignment: Alignment.center, + children: [ + AnimatedOpacity( + duration: Dimens.durationM, + opacity: _isLoading ? Dimens.disabledOpacity : Dimens.enabledOpacity, + child: _Products( + monthly: monthly, + yearly: yearly, + lifetime: lifetime, + selected: selected, + onProductSelected: _selectProduct, + ), + ), + if (_isLoading) + const SizedBox( + height: 120, + child: Center(child: CircularProgressIndicator()), + ), + ], ), const SizedBox(height: Dimens.grid8), FilledButtonLarge( title: S.of(context).continuePurchase, - onPressed: selected != null - ? () { - IAPProductsProvider.of(context).buyPro(selected!); - } - : null, + onPressed: _isLoading || selected != null ? _buyPro : null, ), ], ), ); } + + void _selectProduct(IAPProduct product) { + if (!_isLoading) { + setState(() { + selected = product; + }); + } + } + + Future _buyPro() async { + setState(() { + _isLoading = true; + }); + try { + final isPro = await IAPProductsProvider.of(context).buyPro(selected!); + if (mounted && isPro) { + Navigator.of(context).pop(); + } + } on PlatformException catch (e) { + _showSnackbar(e.message ?? ''); + } catch (e) { + _showSnackbar(e.toString()); + } finally { + if (mounted) { + setState(() { + _isLoading = false; + }); + } + } + } + + void _showSnackbar(String message) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(message), + behavior: SnackBarBehavior.floating, + ), + ); + } + } } class _Products extends StatelessWidget {