@kirz/react-native-toolkit
Version:
Toolkit to speed up React Native development
108 lines • 4.22 kB
JavaScript
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