@neko-os/rc-subscription 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +142 -0
- package/dist/config.js +5 -0
- package/dist/containers/SubscriptionHandler.js +75 -0
- package/dist/containers/SubscriptionRequired.js +11 -0
- package/dist/containers/SubscriptionRequiredCTA.js +37 -0
- package/dist/containers/paywall/Paywall.js +130 -0
- package/dist/containers/paywall/PaywallFeatures.js +42 -0
- package/dist/containers/paywall/PaywallFooter.js +16 -0
- package/dist/containers/paywall/PaywallHero.js +33 -0
- package/dist/containers/paywall/PaywallPlanCard.js +71 -0
- package/dist/containers/paywall/PaywallReturnIcon.js +8 -0
- package/dist/containers/paywall/_request/usePaywallActions.js +39 -0
- package/dist/index.js +6 -0
- package/dist/locales/cs.js +30 -0
- package/dist/locales/da.js +30 -0
- package/dist/locales/de.js +30 -0
- package/dist/locales/el.js +30 -0
- package/dist/locales/en.js +30 -0
- package/dist/locales/es.js +30 -0
- package/dist/locales/fi.js +30 -0
- package/dist/locales/fr.js +30 -0
- package/dist/locales/hi.js +30 -0
- package/dist/locales/hu.js +30 -0
- package/dist/locales/id.js +30 -0
- package/dist/locales/index.js +63 -0
- package/dist/locales/it.js +30 -0
- package/dist/locales/ja.js +30 -0
- package/dist/locales/ko.js +30 -0
- package/dist/locales/nl.js +30 -0
- package/dist/locales/no.js +30 -0
- package/dist/locales/pl.js +30 -0
- package/dist/locales/pt.js +30 -0
- package/dist/locales/ro.js +30 -0
- package/dist/locales/ru.js +30 -0
- package/dist/locales/sv.js +30 -0
- package/dist/locales/th.js +30 -0
- package/dist/locales/tr.js +30 -0
- package/dist/locales/uk.js +30 -0
- package/dist/locales/vi.js +30 -0
- package/dist/locales/zh.js +30 -0
- package/dist/views/active/ActiveSubscriptionView.js +51 -0
- package/package.json +53 -0
- package/src/config.js +5 -0
- package/src/containers/SubscriptionHandler.js +75 -0
- package/src/containers/SubscriptionRequired.js +11 -0
- package/src/containers/SubscriptionRequiredCTA.js +37 -0
- package/src/containers/paywall/Paywall.js +130 -0
- package/src/containers/paywall/PaywallFeatures.js +42 -0
- package/src/containers/paywall/PaywallFooter.js +16 -0
- package/src/containers/paywall/PaywallHero.js +33 -0
- package/src/containers/paywall/PaywallPlanCard.js +71 -0
- package/src/containers/paywall/PaywallReturnIcon.js +8 -0
- package/src/containers/paywall/_request/usePaywallActions.js +39 -0
- package/src/index.js +6 -0
- package/src/locales/cs.js +30 -0
- package/src/locales/da.js +30 -0
- package/src/locales/de.js +30 -0
- package/src/locales/el.js +30 -0
- package/src/locales/en.js +30 -0
- package/src/locales/es.js +30 -0
- package/src/locales/fi.js +30 -0
- package/src/locales/fr.js +30 -0
- package/src/locales/hi.js +30 -0
- package/src/locales/hu.js +30 -0
- package/src/locales/id.js +30 -0
- package/src/locales/index.js +63 -0
- package/src/locales/it.js +30 -0
- package/src/locales/ja.js +30 -0
- package/src/locales/ko.js +30 -0
- package/src/locales/nl.js +30 -0
- package/src/locales/no.js +30 -0
- package/src/locales/pl.js +30 -0
- package/src/locales/pt.js +30 -0
- package/src/locales/ro.js +30 -0
- package/src/locales/ru.js +30 -0
- package/src/locales/sv.js +30 -0
- package/src/locales/th.js +30 -0
- package/src/locales/tr.js +30 -0
- package/src/locales/uk.js +30 -0
- package/src/locales/vi.js +30 -0
- package/src/locales/zh.js +30 -0
- package/src/views/active/ActiveSubscriptionView.js +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# neko-rc-subscription
|
|
2
|
+
|
|
3
|
+
Drop-in RevenueCat subscription module for React Native (Expo) apps built with `@neko-os/ui`. Provides a full paywall, subscription gating, and subscription management — with i18n support for 26 languages.
|
|
4
|
+
|
|
5
|
+
## Peer Dependencies
|
|
6
|
+
|
|
7
|
+
- `react-native-purchases` (RevenueCat SDK)
|
|
8
|
+
- `@neko-os/ui`
|
|
9
|
+
- `@react-navigation/native`
|
|
10
|
+
- `react-native-reanimated`
|
|
11
|
+
- `react-native-safe-area-context`
|
|
12
|
+
- `i18next`
|
|
13
|
+
- `dayjs`
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
Environment variables (or defaults):
|
|
18
|
+
|
|
19
|
+
| Variable | Default | Description |
|
|
20
|
+
|----------|---------|-------------|
|
|
21
|
+
| `EXPO_PUBLIC_RC_API_KEY_IOS` | — | RevenueCat API key for iOS |
|
|
22
|
+
| `EXPO_PUBLIC_RC_API_KEY_ANDROID` | — | RevenueCat API key for Android |
|
|
23
|
+
| `EXPO_PUBLIC_RC_ENTITLEMENT_ID` | `premium` | RevenueCat entitlement identifier |
|
|
24
|
+
|
|
25
|
+
Platform-specific API key selected automatically via `Platform.OS`.
|
|
26
|
+
|
|
27
|
+
## Setup
|
|
28
|
+
|
|
29
|
+
### 1. Register locales
|
|
30
|
+
|
|
31
|
+
Call once at app boot, after i18n is initialized:
|
|
32
|
+
|
|
33
|
+
```jsx
|
|
34
|
+
import { registerSubscriptionLocales } from 'neko-rc-subscription'
|
|
35
|
+
|
|
36
|
+
registerSubscriptionLocales(i18n)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. Wrap your app
|
|
40
|
+
|
|
41
|
+
```jsx
|
|
42
|
+
import { SubscriptionHandler } from 'neko-rc-subscription'
|
|
43
|
+
|
|
44
|
+
<SubscriptionHandler
|
|
45
|
+
paywallConfig={{
|
|
46
|
+
title: 'Unlock Full Access',
|
|
47
|
+
subtitle: 'Track your habits without limits',
|
|
48
|
+
image: require('./assets/paywall-hero.png'),
|
|
49
|
+
features: [
|
|
50
|
+
{ label: 'paywall.unlimitedGoals', icon: 'flag-fill', free: false },
|
|
51
|
+
{ label: 'paywall.analytics', icon: 'bar-chart-fill', free: false },
|
|
52
|
+
{ label: 'paywall.basicTracking', icon: 'check-line', free: true },
|
|
53
|
+
],
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
<App />
|
|
57
|
+
</SubscriptionHandler>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 3. Add routes
|
|
61
|
+
|
|
62
|
+
```jsx
|
|
63
|
+
import { ActiveSubscriptionView } from 'neko-rc-subscription'
|
|
64
|
+
|
|
65
|
+
// Stack navigator
|
|
66
|
+
<Stack.Screen name="subscription/active" component={ActiveSubscriptionView} />
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Exports
|
|
70
|
+
|
|
71
|
+
### Components
|
|
72
|
+
|
|
73
|
+
| Export | Description |
|
|
74
|
+
|--------|-------------|
|
|
75
|
+
| `SubscriptionHandler` | Context provider. Configures RevenueCat, fetches offerings and customer info, provides subscription state to the tree. |
|
|
76
|
+
| `SubscriptionRequired` | Gate component. Shows children if subscribed, otherwise renders the Paywall. |
|
|
77
|
+
| `SubscriptionRequiredCTA` | Soft gate. Renders children with a blurred overlay and "Unlock" button when not subscribed. |
|
|
78
|
+
| `Paywall` | Full paywall screen with hero image, feature comparison, plan selection, purchase and restore. |
|
|
79
|
+
| `ActiveSubscriptionView` | Subscription management screen showing plan details and expiry. |
|
|
80
|
+
|
|
81
|
+
### Hooks
|
|
82
|
+
|
|
83
|
+
| Export | Description |
|
|
84
|
+
|--------|-------------|
|
|
85
|
+
| `useSubscription()` | Full subscription context: `{ isSubscribed, isLoading, customerInfo, offerings, paywallConfig, refresh }` |
|
|
86
|
+
| `useIsSubscribed()` | Shorthand boolean — `true` when active entitlement exists. |
|
|
87
|
+
|
|
88
|
+
### Functions
|
|
89
|
+
|
|
90
|
+
| Export | Description |
|
|
91
|
+
|--------|-------------|
|
|
92
|
+
| `registerSubscriptionLocales(i18n)` | Registers the `subscription` namespace into an existing i18next instance for all 26 supported languages. |
|
|
93
|
+
|
|
94
|
+
## SubscriptionHandler Props
|
|
95
|
+
|
|
96
|
+
| Prop | Type | Description |
|
|
97
|
+
|------|------|-------------|
|
|
98
|
+
| `paywallConfig` | `object` | Optional paywall customization (see below). |
|
|
99
|
+
|
|
100
|
+
### paywallConfig
|
|
101
|
+
|
|
102
|
+
| Key | Type | Description |
|
|
103
|
+
|-----|------|-------------|
|
|
104
|
+
| `title` | `string` | Hero title. Falls back to `t('paywall.title')`. |
|
|
105
|
+
| `subtitle` | `string` | Hero subtitle. Falls back to `t('paywall.subtitle')`. |
|
|
106
|
+
| `image` | `ImageSource` | Hero image (parallax). Omit for text-only hero. |
|
|
107
|
+
| `features` | `Feature[]` | Feature comparison rows. Each: `{ label, icon?, free? }`. `label` is a i18n key. `free` marks whether available on the free plan. |
|
|
108
|
+
|
|
109
|
+
## SubscriptionRequired Props
|
|
110
|
+
|
|
111
|
+
| Prop | Type | Default | Description |
|
|
112
|
+
|------|------|---------|-------------|
|
|
113
|
+
| `disabled` | `bool` | `false` | Bypass the gate (always show children). |
|
|
114
|
+
| `modal` | `bool` | — | Paywall rendered as modal (close icon instead of back arrow). |
|
|
115
|
+
| `showReturn` | `bool` | — | Show return icon on the paywall. |
|
|
116
|
+
| `footerPaddingB` | `number` | — | Override footer bottom padding. |
|
|
117
|
+
|
|
118
|
+
## SubscriptionRequiredCTA Props
|
|
119
|
+
|
|
120
|
+
| Prop | Type | Default | Description |
|
|
121
|
+
|------|------|---------|-------------|
|
|
122
|
+
| `disabled` | `bool` | `false` | Bypass the gate. |
|
|
123
|
+
| `size` | `string` | `'xs'` | Button size. |
|
|
124
|
+
| `buttonProps` | `object` | — | Extra props forwarded to the unlock Button. |
|
|
125
|
+
|
|
126
|
+
## Package Support
|
|
127
|
+
|
|
128
|
+
The paywall auto-renders available packages from the current RevenueCat offering. Supported package types:
|
|
129
|
+
|
|
130
|
+
- **Annual** — shows per-month price and save percentage vs monthly
|
|
131
|
+
- **Monthly** — base reference price
|
|
132
|
+
- **Lifetime** — one-time purchase
|
|
133
|
+
|
|
134
|
+
Free trial detection is automatic from `introPrice` metadata.
|
|
135
|
+
|
|
136
|
+
## i18n
|
|
137
|
+
|
|
138
|
+
Namespace: `subscription`
|
|
139
|
+
|
|
140
|
+
26 languages: cs, da, de, el, en, es, fi, fr, hi, hu, id, it, ja, ko, nl, no, pl, pt, ro, ru, sv, th, tr, uk, vi, zh.
|
|
141
|
+
|
|
142
|
+
Translation keys are organized under `settings`, `paywall`, `cta`, and `active` groups. See `locales/en.js` for the full key reference.
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Platform } from "react-native-web";
|
|
2
|
+
|
|
3
|
+
export var RC_API_KEY =
|
|
4
|
+
Platform.OS === 'ios' ? process.env.EXPO_PUBLIC_RC_API_KEY_IOS : process.env.EXPO_PUBLIC_RC_API_KEY_ANDROID;
|
|
5
|
+
export var RC_ENTITLEMENT_ID = process.env.EXPO_PUBLIC_RC_ENTITLEMENT_ID || 'premium';
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
var _jsxFileName = "/Users/christianstorch/Apps/nekoapps/libs/neko-rc-subscription/src/containers/SubscriptionHandler.js";function _slicedToArray(r, e) {return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();}function _nonIterableRest() {throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");}function _unsupportedIterableToArray(r, a) {if (r) {if ("string" == typeof r) return _arrayLikeToArray(r, a);var t = {}.toString.call(r).slice(8, -1);return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;}}function _arrayLikeToArray(r, a) {(null == a || a > r.length) && (a = r.length);for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];return n;}function _iterableToArrayLimit(r, l) {var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];if (null != t) {var e,n,i,u,a = [],f = !0,o = !1;try {if (i = (t = t.call(r)).next, 0 === l) {if (Object(t) !== t) return;f = !1;} else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);} catch (r) {o = !0, n = r;} finally {try {if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;} finally {if (o) throw n;}}return a;}}function _arrayWithHoles(r) {if (Array.isArray(r)) return r;}function asyncGeneratorStep(n, t, e, r, o, a, c) {try {var i = n[a](c),u = i.value;} catch (n) {return void e(n);}i.done ? t(u) : Promise.resolve(u).then(r, o);}function _asyncToGenerator(n) {return function () {var t = this,e = arguments;return new Promise(function (r, o) {var a = n.apply(t, e);function _next(n) {asyncGeneratorStep(a, r, o, _next, _throw, "next", n);}function _throw(n) {asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);}_next(void 0);});};}import React, { createContext, useContext, useEffect, useState } from 'react';
|
|
2
|
+
import Purchases from 'react-native-purchases';
|
|
3
|
+
|
|
4
|
+
import { RC_API_KEY, RC_ENTITLEMENT_ID } from "../config";import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
var SubscriptionContext = createContext({
|
|
7
|
+
isSubscribed: false,
|
|
8
|
+
isLoading: true,
|
|
9
|
+
customerInfo: null,
|
|
10
|
+
offerings: null,
|
|
11
|
+
paywallConfig: null,
|
|
12
|
+
refresh: function () {var _refresh = _asyncToGenerator(function* () {});function refresh() {return _refresh.apply(this, arguments);}return refresh;}()
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export function useSubscription() {
|
|
16
|
+
return useContext(SubscriptionContext);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function useIsSubscribed() {
|
|
20
|
+
return useContext(SubscriptionContext).isSubscribed;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default function SubscriptionHandler(_ref) {var children = _ref.children,paywallConfig = _ref.paywallConfig;
|
|
24
|
+
var _useState = useState(false),_useState2 = _slicedToArray(_useState, 2),isSubscribed = _useState2[0],setIsSubscribed = _useState2[1];
|
|
25
|
+
var _useState3 = useState(true),_useState4 = _slicedToArray(_useState3, 2),isLoading = _useState4[0],setIsLoading = _useState4[1];
|
|
26
|
+
var _useState5 = useState(null),_useState6 = _slicedToArray(_useState5, 2),customerInfo = _useState6[0],setCustomerInfo = _useState6[1];
|
|
27
|
+
var _useState7 = useState(null),_useState8 = _slicedToArray(_useState7, 2),offerings = _useState8[0],setOfferings = _useState8[1];function
|
|
28
|
+
|
|
29
|
+
refresh() {return _refresh2.apply(this, arguments);}function _refresh2() {_refresh2 = _asyncToGenerator(function* () {
|
|
30
|
+
try {var _info$entitlements2, _info$entitlements2$a;
|
|
31
|
+
var info = yield Purchases.getCustomerInfo();
|
|
32
|
+
setCustomerInfo(info);
|
|
33
|
+
setIsSubscribed(!!(info != null && (_info$entitlements2 = info.entitlements) != null && (_info$entitlements2$a = _info$entitlements2.active) != null && _info$entitlements2$a[RC_ENTITLEMENT_ID]));
|
|
34
|
+
} catch (_) {}
|
|
35
|
+
});return _refresh2.apply(this, arguments);}
|
|
36
|
+
|
|
37
|
+
useEffect(function () {
|
|
38
|
+
if (!RC_API_KEY) {
|
|
39
|
+
setIsLoading(false);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function handleCustomerInfo(info) {var _info$entitlements, _info$entitlements$ac;
|
|
44
|
+
setCustomerInfo(info);
|
|
45
|
+
setIsSubscribed(!!(info != null && (_info$entitlements = info.entitlements) != null && (_info$entitlements$ac = _info$entitlements.active) != null && _info$entitlements$ac[RC_ENTITLEMENT_ID]));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Purchases.configure({ apiKey: RC_API_KEY });
|
|
49
|
+
|
|
50
|
+
_asyncToGenerator(function* () {
|
|
51
|
+
try {
|
|
52
|
+
var _yield$Promise$all = yield Promise.all([
|
|
53
|
+
Purchases.getCustomerInfo(),
|
|
54
|
+
Purchases.getOfferings()]
|
|
55
|
+
),_yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 2),info = _yield$Promise$all2[0],offeringsResult = _yield$Promise$all2[1];
|
|
56
|
+
handleCustomerInfo(info);
|
|
57
|
+
setOfferings(offeringsResult);
|
|
58
|
+
} catch (_) {
|
|
59
|
+
} finally {
|
|
60
|
+
setIsLoading(false);
|
|
61
|
+
}
|
|
62
|
+
})();
|
|
63
|
+
|
|
64
|
+
Purchases.addCustomerInfoUpdateListener(handleCustomerInfo);
|
|
65
|
+
return function () {return Purchases.removeCustomerInfoUpdateListener(handleCustomerInfo);};
|
|
66
|
+
}, []);
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
_jsx(SubscriptionContext.Provider, {
|
|
70
|
+
value: { isSubscribed: isSubscribed, isLoading: isLoading, customerInfo: customerInfo, offerings: offerings, paywallConfig: paywallConfig, refresh: refresh }, children:
|
|
71
|
+
|
|
72
|
+
children }
|
|
73
|
+
));
|
|
74
|
+
|
|
75
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
var _jsxFileName = "/Users/christianstorch/Apps/nekoapps/libs/neko-rc-subscription/src/containers/SubscriptionRequired.js";import { Loading } from '@neko-os/ui';
|
|
2
|
+
|
|
3
|
+
import Paywall from "./paywall/Paywall";
|
|
4
|
+
import { useSubscription } from "./SubscriptionHandler";import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
export default function SubscriptionRequired(_ref) {var children = _ref.children,_ref$disabled = _ref.disabled,disabled = _ref$disabled === void 0 ? false : _ref$disabled,modal = _ref.modal,showReturn = _ref.showReturn,footerPaddingB = _ref.footerPaddingB;
|
|
7
|
+
var _useSubscription = useSubscription(),isSubscribed = _useSubscription.isSubscribed,isLoading = _useSubscription.isLoading;
|
|
8
|
+
if (disabled || isSubscribed) return children;
|
|
9
|
+
if (isLoading) return _jsx(Loading, {});
|
|
10
|
+
return _jsx(Paywall, { modal: modal, showReturn: showReturn, footerPaddingB: footerPaddingB });
|
|
11
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
var _jsxFileName = "/Users/christianstorch/Apps/nekoapps/libs/neko-rc-subscription/src/containers/SubscriptionRequiredCTA.js";var _excluded = ["children", "disabled", "hideButton", "size", "buttonProps"];function _objectWithoutProperties(e, t) {if (null == e) return {};var o,r,i = _objectWithoutPropertiesLoose(e, t);if (Object.getOwnPropertySymbols) {var n = Object.getOwnPropertySymbols(e);for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);}return i;}function _objectWithoutPropertiesLoose(r, e) {if (null == r) return {};var t = {};for (var n in r) if ({}.hasOwnProperty.call(r, n)) {if (-1 !== e.indexOf(n)) continue;t[n] = r[n];}return t;}import { BlurView, Button, View, useTranslation } from '@neko-os/ui';
|
|
2
|
+
import { useNavigation } from '@react-navigation/native';
|
|
3
|
+
|
|
4
|
+
import { useIsSubscribed } from "./SubscriptionHandler";import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
export default function SubscriptionRequiredCTA(_ref)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
{var children = _ref.children,_ref$disabled = _ref.disabled,disabled = _ref$disabled === void 0 ? false : _ref$disabled,_ref$hideButton = _ref.hideButton,hideButton = _ref$hideButton === void 0 ? false : _ref$hideButton,size = _ref.size,buttonProps = _ref.buttonProps,props = _objectWithoutProperties(_ref, _excluded);
|
|
14
|
+
var _useTranslation = useTranslation('subscription'),t = _useTranslation.t;
|
|
15
|
+
var _useNavigation = useNavigation(),navigate = _useNavigation.navigate;
|
|
16
|
+
var isSubscribed = useIsSubscribed();
|
|
17
|
+
|
|
18
|
+
if (disabled || isSubscribed) return children;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
_jsxs(View, Object.assign({ relative: true, hiddenOverflow: true }, props, { children: [
|
|
22
|
+
children,
|
|
23
|
+
_jsx(BlurView, { absoluteFill: true, center: true, zIndex: 10, intensity: 18, onPress: function onPress() {return navigate('subscription/active');}, children:
|
|
24
|
+
!hideButton &&
|
|
25
|
+
_jsx(Button, Object.assign({
|
|
26
|
+
label: t('cta.unlock'),
|
|
27
|
+
icon: "trophy-fill",
|
|
28
|
+
yellow: true,
|
|
29
|
+
size: size || 'xs' },
|
|
30
|
+
buttonProps, {
|
|
31
|
+
onPress: function onPress() {return navigate('subscription/active');} })
|
|
32
|
+
) }
|
|
33
|
+
|
|
34
|
+
)] })
|
|
35
|
+
));
|
|
36
|
+
|
|
37
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
var _jsxFileName = "/Users/christianstorch/Apps/nekoapps/libs/neko-rc-subscription/src/containers/paywall/Paywall.js";function _slicedToArray(r, e) {return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();}function _nonIterableRest() {throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");}function _unsupportedIterableToArray(r, a) {if (r) {if ("string" == typeof r) return _arrayLikeToArray(r, a);var t = {}.toString.call(r).slice(8, -1);return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;}}function _arrayLikeToArray(r, a) {(null == a || a > r.length) && (a = r.length);for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];return n;}function _iterableToArrayLimit(r, l) {var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];if (null != t) {var e,n,i,u,a = [],f = !0,o = !1;try {if (i = (t = t.call(r)).next, 0 === l) {if (Object(t) !== t) return;f = !1;} else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);} catch (r) {o = !0, n = r;} finally {try {if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;} finally {if (o) throw n;}}return a;}}function _arrayWithHoles(r) {if (Array.isArray(r)) return r;}import {
|
|
2
|
+
AnimatedTopBar,
|
|
3
|
+
BlurView,
|
|
4
|
+
ReanimatedScrollHandler,
|
|
5
|
+
ScrollView,
|
|
6
|
+
View,
|
|
7
|
+
useReanimatedScroll,
|
|
8
|
+
useTranslation } from
|
|
9
|
+
'@neko-os/ui';
|
|
10
|
+
import { Platform } from "react-native-web";
|
|
11
|
+
import { useState } from 'react';
|
|
12
|
+
import Animated from 'react-native-reanimated';
|
|
13
|
+
|
|
14
|
+
import { useSubscription } from "../SubscriptionHandler";
|
|
15
|
+
import PaywallFeatures from "./PaywallFeatures";
|
|
16
|
+
import PaywallFooter from "./PaywallFooter";
|
|
17
|
+
import PaywallHero from "./PaywallHero";
|
|
18
|
+
import PaywallPlanCard from "./PaywallPlanCard";
|
|
19
|
+
import PaywallReturnIcon from "./PaywallReturnIcon";
|
|
20
|
+
import usePaywallActions from "./_request/usePaywallActions";import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
21
|
+
|
|
22
|
+
var AnimatedScrollView = Animated.createAnimatedComponent(ScrollView);
|
|
23
|
+
|
|
24
|
+
function getAvailablePackages(offerings) {
|
|
25
|
+
if (!(offerings != null && offerings.current)) return [];
|
|
26
|
+
var _offerings$current = offerings.current,annual = _offerings$current.annual,monthly = _offerings$current.monthly,lifetime = _offerings$current.lifetime;
|
|
27
|
+
return [annual, monthly, lifetime].filter(Boolean);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function getTrialDays(pkg) {var _pkg$product, _intro$periodUnit;
|
|
31
|
+
var intro = pkg == null ? void 0 : (_pkg$product = pkg.product) == null ? void 0 : _pkg$product.introPrice;
|
|
32
|
+
if (!intro || intro.price > 0) return null;
|
|
33
|
+
var units = intro.periodNumberOfUnits || 0;
|
|
34
|
+
var unit = (_intro$periodUnit = intro.periodUnit) == null ? void 0 : _intro$periodUnit.toUpperCase();
|
|
35
|
+
if (unit === 'DAY') return units;
|
|
36
|
+
if (unit === 'WEEK') return units * 7;
|
|
37
|
+
if (unit === 'MONTH') return units * 30;
|
|
38
|
+
return units;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function PaywallScrollContent(_ref)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
{var _this = this;var image = _ref.image,title = _ref.title,subtitle = _ref.subtitle,features = _ref.features,packages = _ref.packages,selectedPkg = _ref.selectedPkg,onSelect = _ref.onSelect,monthlyPrice = _ref.monthlyPrice,showReturnIcon = _ref.showReturnIcon,modal = _ref.modal;
|
|
53
|
+
var _useReanimatedScroll = useReanimatedScroll(),scrollHandler = _useReanimatedScroll.scrollHandler;
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
_jsxs(AnimatedScrollView, { onScroll: scrollHandler, children: [
|
|
57
|
+
_jsx(PaywallHero, { image: image, title: title, subtitle: subtitle, showReturnIcon: showReturnIcon, modal: modal }),
|
|
58
|
+
_jsx(PaywallFeatures, { features: features }),
|
|
59
|
+
|
|
60
|
+
_jsx(View, { gap: "xs", paddingH: "md", paddingT: "sm", children:
|
|
61
|
+
packages.map(function (pkg) {return (
|
|
62
|
+
_jsx(PaywallPlanCard, {
|
|
63
|
+
|
|
64
|
+
pkg: pkg,
|
|
65
|
+
selected: (selectedPkg == null ? void 0 : selectedPkg.identifier) === pkg.identifier,
|
|
66
|
+
onSelect: onSelect,
|
|
67
|
+
monthlyPrice: monthlyPrice }, pkg.identifier
|
|
68
|
+
));}
|
|
69
|
+
) }
|
|
70
|
+
),
|
|
71
|
+
_jsx(View, { height: 200 })] }
|
|
72
|
+
));
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export default function Paywall(_ref2) {var _packages$find, _packages$find$produc;var modal = _ref2.modal,showReturn = _ref2.showReturn,footerPaddingB = _ref2.footerPaddingB;
|
|
77
|
+
var _useTranslation = useTranslation('subscription'),t = _useTranslation.t;
|
|
78
|
+
var _useSubscription = useSubscription(),offerings = _useSubscription.offerings,paywallConfig = _useSubscription.paywallConfig;
|
|
79
|
+
var _usePaywallActions = usePaywallActions(),handlePurchase = _usePaywallActions.handlePurchase,handleRestore = _usePaywallActions.handleRestore,loading = _usePaywallActions.loading;
|
|
80
|
+
|
|
81
|
+
var packages = getAvailablePackages(offerings);
|
|
82
|
+
var _useState = useState(function () {return packages[0] || null;}),_useState2 = _slicedToArray(_useState, 2),selectedPkg = _useState2[0],setSelectedPkg = _useState2[1];
|
|
83
|
+
|
|
84
|
+
var monthlyPrice = (_packages$find = packages.find(function (p) {return p.packageType === 'MONTHLY';})) == null ? void 0 : (_packages$find$produc = _packages$find.product) == null ? void 0 : _packages$find$produc.price;
|
|
85
|
+
var trialDays = getTrialDays(selectedPkg);
|
|
86
|
+
|
|
87
|
+
var title = (paywallConfig == null ? void 0 : paywallConfig.title) || t('paywall.title');
|
|
88
|
+
var subtitle = (paywallConfig == null ? void 0 : paywallConfig.subtitle) || t('paywall.subtitle');
|
|
89
|
+
var image = paywallConfig == null ? void 0 : paywallConfig.image;
|
|
90
|
+
var features = paywallConfig == null ? void 0 : paywallConfig.features;
|
|
91
|
+
var showReturnIcon = modal || showReturn;
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
_jsxs(View, { flex: true, bg: "mainBG", children: [
|
|
95
|
+
_jsxs(ReanimatedScrollHandler, { children: [
|
|
96
|
+
_jsx(AnimatedTopBar, {
|
|
97
|
+
WrapperView: BlurView,
|
|
98
|
+
title: title,
|
|
99
|
+
subtitle: subtitle,
|
|
100
|
+
slide: true,
|
|
101
|
+
shadow: true,
|
|
102
|
+
showAfter: 230,
|
|
103
|
+
useSafeArea: !(modal && Platform.OS === 'ios'),
|
|
104
|
+
left: showReturnIcon && _jsx(PaywallReturnIcon, { modal: modal }) }
|
|
105
|
+
),
|
|
106
|
+
|
|
107
|
+
_jsx(PaywallScrollContent, {
|
|
108
|
+
image: image,
|
|
109
|
+
title: title,
|
|
110
|
+
subtitle: subtitle,
|
|
111
|
+
features: features,
|
|
112
|
+
packages: packages,
|
|
113
|
+
selectedPkg: selectedPkg,
|
|
114
|
+
onSelect: setSelectedPkg,
|
|
115
|
+
monthlyPrice: monthlyPrice,
|
|
116
|
+
showReturnIcon: showReturnIcon,
|
|
117
|
+
modal: modal }
|
|
118
|
+
)] }
|
|
119
|
+
),
|
|
120
|
+
|
|
121
|
+
_jsx(PaywallFooter, {
|
|
122
|
+
onPurchase: function onPurchase() {return handlePurchase(selectedPkg);},
|
|
123
|
+
onRestore: handleRestore,
|
|
124
|
+
loading: loading,
|
|
125
|
+
trialDays: trialDays,
|
|
126
|
+
footerPaddingB: footerPaddingB }
|
|
127
|
+
)] }
|
|
128
|
+
));
|
|
129
|
+
|
|
130
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
var _jsxFileName = "/Users/christianstorch/Apps/nekoapps/libs/neko-rc-subscription/src/containers/paywall/PaywallFeatures.js";import { Icon, Text, View, useTranslation } from '@neko-os/ui';import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
|
|
3
|
+
export default function PaywallFeatures(_ref) {var _this = this;var features = _ref.features;
|
|
4
|
+
var _useTranslation = useTranslation('subscription'),t = _useTranslation.t;
|
|
5
|
+
|
|
6
|
+
if (!(features != null && features.length)) return null;
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
_jsxs(View, { paddingH: "xl", paddingB: "md", children: [
|
|
10
|
+
_jsxs(View, { row: true, paddingB: "xs", children: [
|
|
11
|
+
_jsx(View, { flex: true }),
|
|
12
|
+
_jsx(Text, { xs: true, text3: true, center: true, width: 40, children:
|
|
13
|
+
t('paywall.free') }
|
|
14
|
+
),
|
|
15
|
+
_jsx(Text, { xs: true, strong: true, center: true, width: 40, color: "primary", children:
|
|
16
|
+
t('paywall.pro') }
|
|
17
|
+
)] }
|
|
18
|
+
),
|
|
19
|
+
|
|
20
|
+
features.map(function (feature, i) {return (
|
|
21
|
+
_jsxs(View, { row: true, centerV: true, paddingV: "sm", children: [
|
|
22
|
+
_jsxs(View, { flex: true, row: true, gap: "sm", centerV: true, children: [
|
|
23
|
+
_jsx(Icon, { name: feature.icon || 'check-line', size: "sm" }),
|
|
24
|
+
_jsx(Text, { sm: true, flex: true, children:
|
|
25
|
+
t(feature.label) }
|
|
26
|
+
)] }
|
|
27
|
+
),
|
|
28
|
+
_jsx(View, { width: 40, center: true, children:
|
|
29
|
+
feature.free ?
|
|
30
|
+
_jsx(Icon, { name: "checkbox-circle-fill", primary: true, size: "sm" }) :
|
|
31
|
+
|
|
32
|
+
_jsx(Icon, { name: "close-circle-fill", color: "text4_op40", size: "sm" }) }
|
|
33
|
+
|
|
34
|
+
),
|
|
35
|
+
_jsx(View, { width: 40, center: true, children:
|
|
36
|
+
_jsx(Icon, { name: "checkbox-circle-fill", primary: true, size: "sm" }) }
|
|
37
|
+
)] }, i
|
|
38
|
+
));}
|
|
39
|
+
)] }
|
|
40
|
+
));
|
|
41
|
+
|
|
42
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
var _jsxFileName = "/Users/christianstorch/Apps/nekoapps/libs/neko-rc-subscription/src/containers/paywall/PaywallFooter.js";import { Button, Link, View, useTranslation } from '@neko-os/ui';
|
|
2
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
export default function PaywallFooter(_ref) {var onPurchase = _ref.onPurchase,onRestore = _ref.onRestore,loading = _ref.loading,trialDays = _ref.trialDays,footerPaddingB = _ref.footerPaddingB;
|
|
5
|
+
var _useTranslation = useTranslation('subscription'),t = _useTranslation.t;
|
|
6
|
+
var _useSafeAreaInsets = useSafeAreaInsets(),bottom = _useSafeAreaInsets.bottom;
|
|
7
|
+
|
|
8
|
+
var ctaLabel = trialDays ? t('paywall.ctaTrial') : t('paywall.cta');
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
_jsxs(View, { gap: "sm", padding: "md", paddingB: footerPaddingB || Math.max(bottom / 2, 16), borderT: true, shadow: !footerPaddingB, children: [
|
|
12
|
+
_jsx(Button, { label: ctaLabel, onPress: onPurchase, disabled: loading, loading: loading }),
|
|
13
|
+
_jsx(Link, { label: t('paywall.restore'), onPress: onRestore, disabled: loading, xs: true, text3: true, center: true, underline: true })] }
|
|
14
|
+
));
|
|
15
|
+
|
|
16
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
var _jsxFileName = "/Users/christianstorch/Apps/nekoapps/libs/neko-rc-subscription/src/containers/paywall/PaywallHero.js";import { Image, ParallaxHeader, SafeAreaView, Text, View } from '@neko-os/ui';
|
|
2
|
+
|
|
3
|
+
import PaywallReturnIcon from "./PaywallReturnIcon";import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
export default function PaywallHero(_ref) {var image = _ref.image,title = _ref.title,subtitle = _ref.subtitle,showReturnIcon = _ref.showReturnIcon,modal = _ref.modal;
|
|
6
|
+
var IMAGE_HEIGHT = modal ? 180 : 280;
|
|
7
|
+
return (
|
|
8
|
+
_jsxs(_Fragment, { children: [
|
|
9
|
+
image &&
|
|
10
|
+
_jsx(ParallaxHeader, { height: IMAGE_HEIGHT, disableResistence: true, children:
|
|
11
|
+
_jsx(Image, { source: image, height: IMAGE_HEIGHT, fullW: true, br: 0 }) }
|
|
12
|
+
),
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
showReturnIcon &&
|
|
16
|
+
_jsx(SafeAreaView, { absolute: true, top: "sm", left: "md", zIndex: 100, children:
|
|
17
|
+
_jsx(PaywallReturnIcon, { modal: modal }) }
|
|
18
|
+
),
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
_jsxs(View, { brT: "xxxl", bg: "mainBG", marginT: -25, paddingH: "md", gap: "xs", paddingV: "xl", children: [
|
|
22
|
+
_jsx(Text, { h2: true, strong: true, center: true, children:
|
|
23
|
+
title }
|
|
24
|
+
),
|
|
25
|
+
subtitle &&
|
|
26
|
+
_jsx(Text, { sm: true, text3: true, center: true, children:
|
|
27
|
+
subtitle }
|
|
28
|
+
)] }
|
|
29
|
+
|
|
30
|
+
)] }
|
|
31
|
+
));
|
|
32
|
+
|
|
33
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
var _jsxFileName = "/Users/christianstorch/Apps/nekoapps/libs/neko-rc-subscription/src/containers/paywall/PaywallPlanCard.js";import { Card, Link, Radio, Tag, Text, View, useTranslation } from '@neko-os/ui';import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
|
|
3
|
+
var TYPE_LABELS = {
|
|
4
|
+
MONTHLY: 'monthly',
|
|
5
|
+
ANNUAL: 'yearly',
|
|
6
|
+
LIFETIME: 'lifetime'
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
function getTrialDays(introPrice) {var _introPrice$periodUni;
|
|
10
|
+
if (!introPrice || introPrice.price > 0) return null;
|
|
11
|
+
var units = introPrice.periodNumberOfUnits || 0;
|
|
12
|
+
var unit = (_introPrice$periodUni = introPrice.periodUnit) == null ? void 0 : _introPrice$periodUni.toUpperCase();
|
|
13
|
+
if (unit === 'DAY') return units;
|
|
14
|
+
if (unit === 'WEEK') return units * 7;
|
|
15
|
+
if (unit === 'MONTH') return units * 30;
|
|
16
|
+
return units;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getSavePercent(monthlyPrice, annualPrice) {
|
|
20
|
+
if (!monthlyPrice || !annualPrice) return null;
|
|
21
|
+
var yearlyFromMonthly = monthlyPrice * 12;
|
|
22
|
+
var percent = Math.round((yearlyFromMonthly - annualPrice) / yearlyFromMonthly * 100);
|
|
23
|
+
return percent > 0 ? percent : null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default function PaywallPlanCard(_ref) {var pkg = _ref.pkg,selected = _ref.selected,onSelect = _ref.onSelect,monthlyPrice = _ref.monthlyPrice;
|
|
27
|
+
var _useTranslation = useTranslation('subscription'),t = _useTranslation.t;
|
|
28
|
+
var product = pkg.product;
|
|
29
|
+
var typeKey = TYPE_LABELS[pkg.packageType] || pkg.packageType;
|
|
30
|
+
var label = t('paywall.' + typeKey, { defaultValue: typeKey });
|
|
31
|
+
|
|
32
|
+
var trialDays = getTrialDays(product.introPrice);
|
|
33
|
+
var savePercent = pkg.packageType === 'ANNUAL' ? getSavePercent(monthlyPrice, product.price) : null;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
_jsx(Link, { onPress: function onPress() {return onSelect(pkg);}, children:
|
|
37
|
+
_jsxs(Card, {
|
|
38
|
+
row: true,
|
|
39
|
+
centerV: true,
|
|
40
|
+
padding: "md",
|
|
41
|
+
gap: "md",
|
|
42
|
+
bg: selected ? 'primary_op10' : 'overlayBG',
|
|
43
|
+
borderColor: selected ? 'primary' : 'divider',
|
|
44
|
+
border: true,
|
|
45
|
+
minH: "xxl", children: [
|
|
46
|
+
|
|
47
|
+
_jsx(Radio, { xs: true, value: selected }),
|
|
48
|
+
|
|
49
|
+
_jsxs(View, { flex: true, gap: "xxs", children: [
|
|
50
|
+
_jsxs(View, { row: true, centerV: true, gap: "xs", children: [
|
|
51
|
+
_jsx(Text, { strong: true, children: label }),
|
|
52
|
+
savePercent && _jsx(Tag, { primary: true, label: t('paywall.save', { percent: savePercent }), fill: true }),
|
|
53
|
+
trialDays && _jsx(Tag, { green: true, label: t('paywall.freeTrial', { count: trialDays }) })] }
|
|
54
|
+
),
|
|
55
|
+
pkg.packageType === 'ANNUAL' && product.pricePerMonthString &&
|
|
56
|
+
_jsx(Text, { xs: true, text3: true, children:
|
|
57
|
+
t('paywall.perMonth', { price: product.pricePerMonthString }) }
|
|
58
|
+
),
|
|
59
|
+
|
|
60
|
+
product.introPrice && product.introPrice.price > 0 &&
|
|
61
|
+
_jsxs(Text, { xs: true, text3: true, children: [
|
|
62
|
+
product.introPrice.priceString, " intro"] }
|
|
63
|
+
)] }
|
|
64
|
+
|
|
65
|
+
),
|
|
66
|
+
|
|
67
|
+
_jsx(Text, { strong: true, children: product.priceString })] }
|
|
68
|
+
) }
|
|
69
|
+
));
|
|
70
|
+
|
|
71
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
var _jsxFileName = "/Users/christianstorch/Apps/nekoapps/libs/neko-rc-subscription/src/containers/paywall/PaywallReturnIcon.js";import { Button } from '@neko-os/ui';
|
|
2
|
+
import { useNavigation } from '@react-navigation/native';import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
export default function PaywallReturnIcon(_ref) {var modal = _ref.modal;
|
|
5
|
+
var _useNavigation = useNavigation(),goBack = _useNavigation.goBack;
|
|
6
|
+
|
|
7
|
+
return _jsx(Button, { icon: modal ? 'close-line' : 'arrow-left-line', ratio: 1, xs: true, color: "mainBG", round: true, onPress: goBack });
|
|
8
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) {try {var i = n[a](c),u = i.value;} catch (n) {return void e(n);}i.done ? t(u) : Promise.resolve(u).then(r, o);}function _asyncToGenerator(n) {return function () {var t = this,e = arguments;return new Promise(function (r, o) {var a = n.apply(t, e);function _next(n) {asyncGeneratorStep(a, r, o, _next, _throw, "next", n);}function _throw(n) {asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);}_next(void 0);});};}function _slicedToArray(r, e) {return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();}function _nonIterableRest() {throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");}function _unsupportedIterableToArray(r, a) {if (r) {if ("string" == typeof r) return _arrayLikeToArray(r, a);var t = {}.toString.call(r).slice(8, -1);return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;}}function _arrayLikeToArray(r, a) {(null == a || a > r.length) && (a = r.length);for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];return n;}function _iterableToArrayLimit(r, l) {var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];if (null != t) {var e,n,i,u,a = [],f = !0,o = !1;try {if (i = (t = t.call(r)).next, 0 === l) {if (Object(t) !== t) return;f = !1;} else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);} catch (r) {o = !0, n = r;} finally {try {if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;} finally {if (o) throw n;}}return a;}}function _arrayWithHoles(r) {if (Array.isArray(r)) return r;}import { Alert } from "react-native-web";
|
|
2
|
+
import { useTranslation } from '@neko-os/ui';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import Purchases from 'react-native-purchases';
|
|
5
|
+
|
|
6
|
+
import { useSubscription } from "../../SubscriptionHandler";
|
|
7
|
+
|
|
8
|
+
export default function usePaywallActions() {
|
|
9
|
+
var _useTranslation = useTranslation('subscription'),t = _useTranslation.t;
|
|
10
|
+
var _useSubscription = useSubscription(),refresh = _useSubscription.refresh;
|
|
11
|
+
var _useState = useState(false),_useState2 = _slicedToArray(_useState, 2),loading = _useState2[0],setLoading = _useState2[1];function
|
|
12
|
+
|
|
13
|
+
handlePurchase(_x) {return _handlePurchase.apply(this, arguments);}function _handlePurchase() {_handlePurchase = _asyncToGenerator(function* (pkg) {
|
|
14
|
+
if (!pkg || loading) return;
|
|
15
|
+
setLoading(true);
|
|
16
|
+
try {
|
|
17
|
+
yield Purchases.purchasePackage(pkg);
|
|
18
|
+
} catch (e) {
|
|
19
|
+
if (!e.userCancelled) Alert.alert(t('paywall.errorTitle', { defaultValue: 'Error' }), e.message);
|
|
20
|
+
} finally {
|
|
21
|
+
setLoading(false);
|
|
22
|
+
}
|
|
23
|
+
});return _handlePurchase.apply(this, arguments);}function
|
|
24
|
+
|
|
25
|
+
handleRestore() {return _handleRestore.apply(this, arguments);}function _handleRestore() {_handleRestore = _asyncToGenerator(function* () {
|
|
26
|
+
if (loading) return;
|
|
27
|
+
setLoading(true);
|
|
28
|
+
try {
|
|
29
|
+
yield Purchases.restorePurchases();
|
|
30
|
+
yield refresh();
|
|
31
|
+
} catch (e) {
|
|
32
|
+
Alert.alert(t('paywall.errorTitle', { defaultValue: 'Error' }), e.message);
|
|
33
|
+
} finally {
|
|
34
|
+
setLoading(false);
|
|
35
|
+
}
|
|
36
|
+
});return _handleRestore.apply(this, arguments);}
|
|
37
|
+
|
|
38
|
+
return { handlePurchase: handlePurchase, handleRestore: handleRestore, loading: loading };
|
|
39
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { registerSubscriptionLocales } from "./locales/index";
|
|
2
|
+
export { default as SubscriptionHandler, useIsSubscribed, useSubscription } from "./containers/SubscriptionHandler";
|
|
3
|
+
export { default as SubscriptionRequired } from "./containers/SubscriptionRequired";
|
|
4
|
+
export { default as SubscriptionRequiredCTA } from "./containers/SubscriptionRequiredCTA";
|
|
5
|
+
export { default as Paywall } from "./containers/paywall/Paywall";
|
|
6
|
+
export { default as ActiveSubscriptionView } from "./views/active/ActiveSubscriptionView";
|