handle purchase errors

This commit is contained in:
Vadim 2025-08-08 13:37:06 +02:00
parent 490aebccd0
commit a9c3489c8e

View file

@ -1,5 +1,7 @@
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/material.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/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/res/theme.dart'; import 'package:lightmeter/res/theme.dart';
@ -30,22 +32,16 @@ class _LightmeterProOfferingState extends State<LightmeterProOffering> {
yearly = products.firstWhereOrNull((p) => p.type == PurchaseType.yearly); yearly = products.firstWhereOrNull((p) => p.type == PurchaseType.yearly);
lifetime = products.firstWhereOrNull((p) => p.type == PurchaseType.lifetime); lifetime = products.firstWhereOrNull((p) => p.type == PurchaseType.lifetime);
selected = monthly ?? lifetime; selected = monthly ?? lifetime;
}).onError((_, __) { }).onError((e, __) {
/// SchedulerBinding.instance.addPostFrameCallback((_) {
_showSnackbar(e.toString());
});
}).whenComplete(() { }).whenComplete(() {
_isLoading = false; _isLoading = false;
if (mounted) setState(() {}); if (mounted) setState(() {});
}); });
} }
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (IAPProducts.isPro(context)) {
Navigator.of(context).pop();
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
@ -67,38 +63,77 @@ class _LightmeterProOfferingState extends State<LightmeterProOffering> {
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
AnimatedSwitcher( Stack(
alignment: Alignment.center,
children: [
AnimatedOpacity(
duration: Dimens.durationM, duration: Dimens.durationM,
child: _isLoading opacity: _isLoading ? Dimens.disabledOpacity : Dimens.enabledOpacity,
? const SizedBox( child: _Products(
height: 120,
child: Center(child: CircularProgressIndicator()),
)
: _Products(
monthly: monthly, monthly: monthly,
yearly: yearly, yearly: yearly,
lifetime: lifetime, lifetime: lifetime,
selected: selected, selected: selected,
onProductSelected: (value) { onProductSelected: _selectProduct,
setState(() {
selected = value;
});
},
), ),
), ),
if (_isLoading)
const SizedBox(
height: 120,
child: Center(child: CircularProgressIndicator()),
),
],
),
const SizedBox(height: Dimens.grid8), const SizedBox(height: Dimens.grid8),
FilledButtonLarge( FilledButtonLarge(
title: S.of(context).continuePurchase, title: S.of(context).continuePurchase,
onPressed: selected != null onPressed: _isLoading || selected != null ? _buyPro : null,
? () {
IAPProductsProvider.of(context).buyPro(selected!);
}
: null,
), ),
], ],
), ),
); );
} }
void _selectProduct(IAPProduct product) {
if (!_isLoading) {
setState(() {
selected = product;
});
}
}
Future<void> _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 { class _Products extends StatelessWidget {