UNPKG

@kirz/react-native-toolkit

Version:

Toolkit to speed up React Native development

108 lines 4.22 kB
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState, useRef } from 'react'; import { PluginsBundleContext } from './PluginsBundleContext'; import { Subscription } from '../plugins/types'; import { waitUntil } from '../utils/promise/waitUntil'; export const InAppPurchaseContext = /*#__PURE__*/createContext({}); export function InAppPurchaseProvider(_ref) { let { children } = _ref; const [isInitialized, setIsInitialized] = useState(false); const { bundle } = useContext(PluginsBundleContext); const iapPurchasePlugin = useMemo(() => { return bundle.getByFeature('InAppPurchase'); }, [bundle]); const [activeSubscription, setActiveSubscription] = useState(null); const [hasPremiumAccess, setHasPremiumAccess] = useState(false); const lastUserDataFetchTimestamp = useRef(new Date().valueOf()); const fetchUserData = useCallback(async () => { if (!iapPurchasePlugin) { throw new Error('IAP is not initialized'); } const results = await Promise.all([iapPurchasePlugin.receiptValidator.hasPremiumAccess(), iapPurchasePlugin.receiptValidator.getActiveSubscription()]); setHasPremiumAccess(results[0]); const subscriptionInstance = results[1] && new Subscription(iapPurchasePlugin.subscriptions.find(x => { var _results$; return x.productId === ((_results$ = results[1]) === null || _results$ === void 0 ? void 0 : _results$.productId); })); setActiveSubscription(subscriptionInstance && results[1] ? { ...subscriptionInstance, ...results[1], formatPrice(options) { return subscriptionInstance.formatPrice(options); } } : null); setIsInitialized(true); lastUserDataFetchTimestamp.current = new Date().valueOf(); return results[0]; }, [iapPurchasePlugin]); const restorePurchases = useCallback(async () => { if (!iapPurchasePlugin) { throw new Error('IAP is not initialized'); } await iapPurchasePlugin.receiptValidator.restorePurchases(); return fetchUserData(); }, [iapPurchasePlugin]); const purchaseProduct = useCallback(async productId => { if (!iapPurchasePlugin) { throw new Error('IAP plugin not found'); } try { const purchase = await iapPurchasePlugin.purchaseProduct(productId); return purchase; } catch (err) { const error = err; if (error.isCancelled) { return null; } throw new Error(error.message); } }, [iapPurchasePlugin]); const purchasePremium = useCallback(async productId => { const purchase = await purchaseProduct(productId); if (!purchase) { return null; } await waitUntil(async () => { await iapPurchasePlugin.receiptValidator.restorePurchases(); return await fetchUserData(); }); await iapPurchasePlugin.refetchProducts(); return purchase; }, [purchaseProduct, iapPurchasePlugin]); const premiumAccess = useCallback(func => { return async function () { let isAllowed = hasPremiumAccess; if (new Date().valueOf() - lastUserDataFetchTimestamp.current > 1000 * 60 * 60) { isAllowed = await restorePurchases(); } if (!isAllowed) { throw new Error('Premium access required'); } return func(...arguments); }; }, [hasPremiumAccess, fetchUserData, restorePurchases]); const contextData = useMemo(() => ({ isInitialized, hasPremiumAccess, activeSubscription, products: (iapPurchasePlugin === null || iapPurchasePlugin === void 0 ? void 0 : iapPurchasePlugin.products) ?? [], subscriptions: (iapPurchasePlugin === null || iapPurchasePlugin === void 0 ? void 0 : iapPurchasePlugin.subscriptions) ?? [], restorePurchases, purchaseProduct, purchasePremium, premiumAccess }), [isInitialized, iapPurchasePlugin, hasPremiumAccess, activeSubscription, restorePurchases, purchaseProduct, purchasePremium, premiumAccess]); useEffect(() => { if (!iapPurchasePlugin) { return; } fetchUserData(); }, [iapPurchasePlugin]); return /*#__PURE__*/React.createElement(InAppPurchaseContext.Provider, { value: contextData }, children); } //# sourceMappingURL=InAppPurchaseContext.js.map