import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:in_app_purchase/in_app_purchase.dart'; import 'constants.dart'; import 'dash_counter.dart'; import 'purchasable_product.dart'; import 'store_state.dart'; class DashPurchases extends ChangeNotifier { DashCounter counter; StoreState storeState = StoreState.loading; late StreamSubscription> _subscription; List products = []; bool get beautifiedDash => _beautifiedDashUpgrade; bool _beautifiedDashUpgrade = false; final iapConnection = IAPConnection.instance; DashPurchases(this.counter) { final purchaseUpdated = iapConnection.purchaseStream; _subscription = purchaseUpdated.listen( _onPurchaseUpdate, onDone: _updateStreamOnDone, onError: _updateStreamOnError, ); loadPurchases(); } Future loadPurchases() async { final available = await iapConnection.isAvailable(); if (!available) { storeState = StoreState.notAvailable; notifyListeners(); return; } const ids = { storeKeyConsumable, storeKeySubscription, storeKeyUpgrade, }; final response = await iapConnection.queryProductDetails(ids); products = response.productDetails.map((e) => PurchasableProduct(e)).toList(); storeState = StoreState.available; notifyListeners(); } @override void dispose() { _subscription.cancel(); super.dispose(); } Future buy(PurchasableProduct product) async { final purchaseParam = PurchaseParam(productDetails: product.productDetails); switch (product.id) { case storeKeyConsumable: await iapConnection.buyConsumable(purchaseParam: purchaseParam); case storeKeySubscription: case storeKeyUpgrade: await iapConnection.buyNonConsumable(purchaseParam: purchaseParam); default: throw ArgumentError.value(product.productDetails, '${product.id} is not a known product'); } } Future _onPurchaseUpdate(List purchaseDetailsList) async { for (var purchaseDetails in purchaseDetailsList) { await _handlePurchase(purchaseDetails); } notifyListeners(); } Future _handlePurchase(PurchaseDetails purchaseDetails) async { if (purchaseDetails.status == PurchaseStatus.purchased) { switch (purchaseDetails.productID) { case storeKeySubscription: counter.applyPaidMultiplier(); case storeKeyConsumable: counter.addBoughtDashes(2000); case storeKeyUpgrade: _beautifiedDashUpgrade = true; } } if (purchaseDetails.pendingCompletePurchase) { await iapConnection.completePurchase(purchaseDetails); } } void _updateStreamOnDone() { _subscription.cancel(); } void _updateStreamOnError(dynamic error) { //Handle error here } }