@neko-os/rc-subscription 0.1.0 → 0.3.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.
Files changed (64) hide show
  1. package/README.md +32 -0
  2. package/dist/config.js +7 -1
  3. package/dist/containers/SubscriptionHandler.js +52 -2
  4. package/dist/containers/SubscriptionRequiredCTA.js +3 -2
  5. package/dist/containers/paywall/Paywall.js +32 -5
  6. package/dist/index.js +1 -1
  7. package/dist/locales/cs.js +2 -0
  8. package/dist/locales/da.js +2 -0
  9. package/dist/locales/de.js +2 -0
  10. package/dist/locales/el.js +2 -0
  11. package/dist/locales/en.js +2 -0
  12. package/dist/locales/es.js +2 -0
  13. package/dist/locales/fi.js +2 -0
  14. package/dist/locales/fr.js +2 -0
  15. package/dist/locales/hi.js +2 -0
  16. package/dist/locales/hu.js +2 -0
  17. package/dist/locales/id.js +2 -0
  18. package/dist/locales/it.js +2 -0
  19. package/dist/locales/ja.js +2 -0
  20. package/dist/locales/ko.js +2 -0
  21. package/dist/locales/nl.js +2 -0
  22. package/dist/locales/no.js +2 -0
  23. package/dist/locales/pl.js +2 -0
  24. package/dist/locales/pt.js +2 -0
  25. package/dist/locales/ro.js +2 -0
  26. package/dist/locales/ru.js +2 -0
  27. package/dist/locales/sv.js +2 -0
  28. package/dist/locales/th.js +2 -0
  29. package/dist/locales/tr.js +2 -0
  30. package/dist/locales/uk.js +2 -0
  31. package/dist/locales/vi.js +2 -0
  32. package/dist/locales/zh.js +2 -0
  33. package/package.json +1 -1
  34. package/src/config.js +6 -0
  35. package/src/containers/SubscriptionHandler.js +52 -2
  36. package/src/containers/SubscriptionRequiredCTA.js +3 -2
  37. package/src/containers/paywall/Paywall.js +28 -1
  38. package/src/index.js +1 -1
  39. package/src/locales/cs.js +2 -0
  40. package/src/locales/da.js +2 -0
  41. package/src/locales/de.js +2 -0
  42. package/src/locales/el.js +2 -0
  43. package/src/locales/en.js +2 -0
  44. package/src/locales/es.js +2 -0
  45. package/src/locales/fi.js +2 -0
  46. package/src/locales/fr.js +2 -0
  47. package/src/locales/hi.js +2 -0
  48. package/src/locales/hu.js +2 -0
  49. package/src/locales/id.js +2 -0
  50. package/src/locales/it.js +2 -0
  51. package/src/locales/ja.js +2 -0
  52. package/src/locales/ko.js +2 -0
  53. package/src/locales/nl.js +2 -0
  54. package/src/locales/no.js +2 -0
  55. package/src/locales/pl.js +2 -0
  56. package/src/locales/pt.js +2 -0
  57. package/src/locales/ro.js +2 -0
  58. package/src/locales/ru.js +2 -0
  59. package/src/locales/sv.js +2 -0
  60. package/src/locales/th.js +2 -0
  61. package/src/locales/tr.js +2 -0
  62. package/src/locales/uk.js +2 -0
  63. package/src/locales/vi.js +2 -0
  64. package/src/locales/zh.js +2 -0
package/README.md CHANGED
@@ -84,6 +84,7 @@ import { ActiveSubscriptionView } from 'neko-rc-subscription'
84
84
  |--------|-------------|
85
85
  | `useSubscription()` | Full subscription context: `{ isSubscribed, isLoading, customerInfo, offerings, paywallConfig, refresh }` |
86
86
  | `useIsSubscribed()` | Shorthand boolean — `true` when active entitlement exists. |
87
+ | `useSubscribedAction(fn?)` | Returns an action wrapper that runs `fn` when subscribed, otherwise opens the paywall. See [Gating an action](#gating-an-action). |
87
88
 
88
89
  ### Functions
89
90
 
@@ -123,6 +124,37 @@ import { ActiveSubscriptionView } from 'neko-rc-subscription'
123
124
  | `size` | `string` | `'xs'` | Button size. |
124
125
  | `buttonProps` | `object` | — | Extra props forwarded to the unlock Button. |
125
126
 
127
+ ## Gating an action
128
+
129
+ `useSubscribedAction` wraps any callback so it only fires for subscribed users — otherwise the paywall opens (navigates to `subscription/active`). Use it for one-off actions that don't warrant a full gate component (`SubscriptionRequired` / `SubscriptionRequiredCTA`).
130
+
131
+ Two equivalent call styles:
132
+
133
+ ```jsx
134
+ import { useSubscribedAction } from 'neko-rc-subscription'
135
+
136
+ // Bind the fn up front
137
+ function ExportButton() {
138
+ const exportData = useSubscribedAction(() => doExport())
139
+ return <Button label="Export" onPress={exportData} />
140
+ }
141
+
142
+ // Bind nothing — pass the fn at call time (handy when the callback varies)
143
+ function Row({ item }) {
144
+ const run = useSubscribedAction()
145
+ return <Button label="Pin" onPress={() => run(() => pin(item))} />
146
+ }
147
+ ```
148
+
149
+ While subscription state is still loading (`isLoading`), the action is a no-op — it neither runs the fn nor opens the paywall, so an already-subscribed user is never bounced to the paywall during init.
150
+
151
+ Arguments are forwarded to the wrapped fn, and its return value is passed through (or `undefined` when the paywall is shown instead):
152
+
153
+ ```jsx
154
+ const save = useSubscribedAction(saveReport)
155
+ save(reportId) // -> saveReport(reportId) when subscribed
156
+ ```
157
+
126
158
  ## Package Support
127
159
 
128
160
  The paywall auto-renders available packages from the current RevenueCat offering. Supported package types:
package/dist/config.js CHANGED
@@ -2,4 +2,10 @@ import { Platform } from "react-native-web";
2
2
 
3
3
  export var RC_API_KEY =
4
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';
5
+ export var RC_ENTITLEMENT_ID = process.env.EXPO_PUBLIC_RC_ENTITLEMENT_ID || 'premium';
6
+ export var PRIVACY_POLICY_URL = process.env.EXPO_PUBLIC_PRIVACY_POLICY_URL;
7
+ export var TERMS_OF_USE_URL = process.env.EXPO_PUBLIC_TERMS_OF_USE_URL;
8
+
9
+
10
+
11
+ export var SUBSCRIPTION_ROUTE = 'subscription/active';
@@ -1,7 +1,8 @@
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';
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 _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 _toConsumableArray(r) {return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();}function _nonIterableSpread() {throw new TypeError("Invalid attempt to spread 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 _iterableToArray(r) {if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);}function _arrayWithoutHoles(r) {if (Array.isArray(r)) return _arrayLikeToArray(r);}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 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, useCallback, useContext, useEffect, useState } from 'react';
2
2
  import Purchases from 'react-native-purchases';
3
+ import { useNavigation } from '@react-navigation/native';
3
4
 
4
- import { RC_API_KEY, RC_ENTITLEMENT_ID } from "../config";import { jsx as _jsx } from "react/jsx-runtime";
5
+ import { RC_API_KEY, RC_ENTITLEMENT_ID, SUBSCRIPTION_ROUTE } from "../config";import { jsx as _jsx } from "react/jsx-runtime";
5
6
 
6
7
  var SubscriptionContext = createContext({
7
8
  isSubscribed: false,
@@ -20,6 +21,55 @@ export function useIsSubscribed() {
20
21
  return useContext(SubscriptionContext).isSubscribed;
21
22
  }
22
23
 
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+ export function useSubscribedAction(boundFn) {
40
+ var _useSubscription = useSubscription(),isSubscribed = _useSubscription.isSubscribed,isLoading = _useSubscription.isLoading;
41
+ var _useNavigation = useNavigation(),navigate = _useNavigation.navigate;
42
+
43
+ return useCallback(
44
+ function () {for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {args[_key] = arguments[_key];}
45
+ var fn = boundFn || args[0];
46
+ var fnArgs = boundFn ? args : args.slice(1);
47
+
48
+ if (typeof fn !== 'function') {
49
+ if (__DEV__) {
50
+ console.warn(
51
+ '[neko-rc-subscription] useSubscribedAction: no function to run — ' +
52
+ 'pass it to the hook `useSubscribedAction(fn)` or to the action `action(fn)`.'
53
+ );
54
+ }
55
+ return undefined;
56
+ }
57
+
58
+
59
+
60
+ if (isLoading) return undefined;
61
+
62
+ if (!isSubscribed) {
63
+ navigate(SUBSCRIPTION_ROUTE);
64
+ return undefined;
65
+ }
66
+
67
+ return fn.apply(void 0, _toConsumableArray(fnArgs));
68
+ },
69
+ [isSubscribed, isLoading, navigate, boundFn]
70
+ );
71
+ }
72
+
23
73
  export default function SubscriptionHandler(_ref) {var children = _ref.children,paywallConfig = _ref.paywallConfig;
24
74
  var _useState = useState(false),_useState2 = _slicedToArray(_useState, 2),isSubscribed = _useState2[0],setIsSubscribed = _useState2[1];
25
75
  var _useState3 = useState(true),_useState4 = _slicedToArray(_useState3, 2),isLoading = _useState4[0],setIsLoading = _useState4[1];
@@ -1,6 +1,7 @@
1
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
2
  import { useNavigation } from '@react-navigation/native';
3
3
 
4
+ import { SUBSCRIPTION_ROUTE } from "../config";
4
5
  import { useIsSubscribed } from "./SubscriptionHandler";import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
6
 
6
7
  export default function SubscriptionRequiredCTA(_ref)
@@ -20,7 +21,7 @@ export default function SubscriptionRequiredCTA(_ref)
20
21
  return (
21
22
  _jsxs(View, Object.assign({ relative: true, hiddenOverflow: true }, props, { children: [
22
23
  children,
23
- _jsx(BlurView, { absoluteFill: true, center: true, zIndex: 10, intensity: 18, onPress: function onPress() {return navigate('subscription/active');}, children:
24
+ _jsx(BlurView, { absoluteFill: true, center: true, zIndex: 10, intensity: 18, onPress: function onPress() {return navigate(SUBSCRIPTION_ROUTE);}, children:
24
25
  !hideButton &&
25
26
  _jsx(Button, Object.assign({
26
27
  label: t('cta.unlock'),
@@ -28,7 +29,7 @@ export default function SubscriptionRequiredCTA(_ref)
28
29
  yellow: true,
29
30
  size: size || 'xs' },
30
31
  buttonProps, {
31
- onPress: function onPress() {return navigate('subscription/active');} })
32
+ onPress: function onPress() {return navigate(SUBSCRIPTION_ROUTE);} })
32
33
  ) }
33
34
 
34
35
  )] })
@@ -1,16 +1,20 @@
1
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
2
  AnimatedTopBar,
3
3
  BlurView,
4
+ Link,
4
5
  ReanimatedScrollHandler,
5
6
  ScrollView,
7
+ Text,
6
8
  View,
7
9
  useReanimatedScroll,
8
10
  useTranslation } from
9
11
  '@neko-os/ui';
10
- import { Platform } from "react-native-web";
12
+ import { Linking, Platform } from "react-native-web";
11
13
  import { useState } from 'react';
12
14
  import Animated from 'react-native-reanimated';
13
15
 
16
+ import { PRIVACY_POLICY_URL, TERMS_OF_USE_URL } from "../../config";
17
+
14
18
  import { useSubscription } from "../SubscriptionHandler";
15
19
  import PaywallFeatures from "./PaywallFeatures";
16
20
  import PaywallFooter from "./PaywallFooter";
@@ -38,7 +42,28 @@ function getTrialDays(pkg) {var _pkg$product, _intro$periodUnit;
38
42
  return units;
39
43
  }
40
44
 
41
- function PaywallScrollContent(_ref)
45
+ function PaywallLegalLinks(_ref) {var t = _ref.t;
46
+ if (!PRIVACY_POLICY_URL && !TERMS_OF_USE_URL) return null;
47
+
48
+ return (
49
+ _jsxs(View, { row: true, center: true, gap: "xs", paddingV: "md", children: [
50
+ PRIVACY_POLICY_URL &&
51
+ _jsx(Link, { onPress: function onPress() {return Linking.openURL(PRIVACY_POLICY_URL);}, children:
52
+ _jsx(Text, { xs: true, text3: true, underline: true, children: t('paywall.privacyPolicy') }) }
53
+ ),
54
+
55
+ PRIVACY_POLICY_URL && TERMS_OF_USE_URL && _jsx(Text, { xs: true, text4: true, children: "\xB7" }),
56
+ TERMS_OF_USE_URL &&
57
+ _jsx(Link, { onPress: function onPress() {return Linking.openURL(TERMS_OF_USE_URL);}, children:
58
+ _jsx(Text, { xs: true, text3: true, underline: true, children: t('paywall.termsOfUse') }) }
59
+ )] }
60
+
61
+ ));
62
+
63
+ }
64
+
65
+ function PaywallScrollContent(_ref2)
66
+
42
67
 
43
68
 
44
69
 
@@ -49,7 +74,7 @@ function PaywallScrollContent(_ref)
49
74
 
50
75
 
51
76
 
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;
77
+ {var _this = this;var image = _ref2.image,title = _ref2.title,subtitle = _ref2.subtitle,features = _ref2.features,packages = _ref2.packages,selectedPkg = _ref2.selectedPkg,onSelect = _ref2.onSelect,monthlyPrice = _ref2.monthlyPrice,showReturnIcon = _ref2.showReturnIcon,modal = _ref2.modal,t = _ref2.t;
53
78
  var _useReanimatedScroll = useReanimatedScroll(),scrollHandler = _useReanimatedScroll.scrollHandler;
54
79
 
55
80
  return (
@@ -68,12 +93,13 @@ function PaywallScrollContent(_ref)
68
93
  ));}
69
94
  ) }
70
95
  ),
96
+ _jsx(PaywallLegalLinks, { t: t }),
71
97
  _jsx(View, { height: 200 })] }
72
98
  ));
73
99
 
74
100
  }
75
101
 
76
- export default function Paywall(_ref2) {var _packages$find, _packages$find$produc;var modal = _ref2.modal,showReturn = _ref2.showReturn,footerPaddingB = _ref2.footerPaddingB;
102
+ export default function Paywall(_ref3) {var _packages$find, _packages$find$produc;var modal = _ref3.modal,showReturn = _ref3.showReturn,footerPaddingB = _ref3.footerPaddingB;
77
103
  var _useTranslation = useTranslation('subscription'),t = _useTranslation.t;
78
104
  var _useSubscription = useSubscription(),offerings = _useSubscription.offerings,paywallConfig = _useSubscription.paywallConfig;
79
105
  var _usePaywallActions = usePaywallActions(),handlePurchase = _usePaywallActions.handlePurchase,handleRestore = _usePaywallActions.handleRestore,loading = _usePaywallActions.loading;
@@ -114,7 +140,8 @@ export default function Paywall(_ref2) {var _packages$find, _packages$find$produ
114
140
  onSelect: setSelectedPkg,
115
141
  monthlyPrice: monthlyPrice,
116
142
  showReturnIcon: showReturnIcon,
117
- modal: modal }
143
+ modal: modal,
144
+ t: t }
118
145
  )] }
119
146
  ),
120
147
 
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { registerSubscriptionLocales } from "./locales/index";
2
- export { default as SubscriptionHandler, useIsSubscribed, useSubscription } from "./containers/SubscriptionHandler";
2
+ export { default as SubscriptionHandler, useIsSubscribed, useSubscribedAction, useSubscription } from "./containers/SubscriptionHandler";
3
3
  export { default as SubscriptionRequired } from "./containers/SubscriptionRequired";
4
4
  export { default as SubscriptionRequiredCTA } from "./containers/SubscriptionRequiredCTA";
5
5
  export { default as Paywall } from "./containers/paywall/Paywall";
@@ -8,6 +8,8 @@ export var subscriptionCS = {
8
8
  cta: 'Pokracovat',
9
9
  ctaTrial: 'Zahajit zkusebni obdobi',
10
10
  restore: 'Obnovit nakupy',
11
+ privacyPolicy: 'Zásady ochrany osobních údajů',
12
+ termsOfUse: 'Podmínky použití',
11
13
  monthly: 'Mesicne',
12
14
  yearly: 'Rocne',
13
15
  lifetime: 'Dozivotne',
@@ -8,6 +8,8 @@ export var subscriptionDA = {
8
8
  cta: 'Fortsaet',
9
9
  ctaTrial: 'Start gratis proveperiode',
10
10
  restore: 'Gendan kob',
11
+ privacyPolicy: 'Privatlivspolitik',
12
+ termsOfUse: 'Brugsvilkår',
11
13
  monthly: 'Manedligt',
12
14
  yearly: 'Arligt',
13
15
  lifetime: 'Livstid',
@@ -8,6 +8,8 @@ export var subscriptionDE = {
8
8
  cta: 'Weiter',
9
9
  ctaTrial: 'Kostenlos testen',
10
10
  restore: 'Kaeufe wiederherstellen',
11
+ privacyPolicy: 'Datenschutzerklärung',
12
+ termsOfUse: 'Nutzungsbedingungen',
11
13
  monthly: 'Monatlich',
12
14
  yearly: 'Jaehrlich',
13
15
  lifetime: 'Lebenslang',
@@ -8,6 +8,8 @@ export var subscriptionEL = {
8
8
  cta: 'Synecheia',
9
9
  ctaTrial: 'Enarxi dorean dokimis',
10
10
  restore: 'Epanafora agoron',
11
+ privacyPolicy: 'Πολιτική Απορρήτου',
12
+ termsOfUse: 'Όροι Χρήσης',
11
13
  monthly: 'Miniaia',
12
14
  yearly: 'Etisia',
13
15
  lifetime: 'Dia viou',
@@ -8,6 +8,8 @@ export var subscriptionEN = {
8
8
  cta: 'Continue',
9
9
  ctaTrial: 'Start free trial',
10
10
  restore: 'Restore purchases',
11
+ privacyPolicy: 'Privacy Policy',
12
+ termsOfUse: 'Terms of Use',
11
13
  monthly: 'Monthly',
12
14
  yearly: 'Yearly',
13
15
  lifetime: 'Lifetime',
@@ -8,6 +8,8 @@ export var subscriptionES = {
8
8
  cta: 'Continuar',
9
9
  ctaTrial: 'Iniciar prueba gratuita',
10
10
  restore: 'Restaurar compras',
11
+ privacyPolicy: 'Política de Privacidad',
12
+ termsOfUse: 'Términos de Uso',
11
13
  monthly: 'Mensual',
12
14
  yearly: 'Anual',
13
15
  lifetime: 'De por vida',
@@ -8,6 +8,8 @@ export var subscriptionFI = {
8
8
  cta: 'Jatka',
9
9
  ctaTrial: 'Aloita ilmainen kokeilu',
10
10
  restore: 'Palauta ostokset',
11
+ privacyPolicy: 'Tietosuojakäytäntö',
12
+ termsOfUse: 'Käyttöehdot',
11
13
  monthly: 'Kuukausittain',
12
14
  yearly: 'Vuosittain',
13
15
  lifetime: 'Elinaika',
@@ -8,6 +8,8 @@ export var subscriptionFR = {
8
8
  cta: 'Continuer',
9
9
  ctaTrial: 'Demarrer l\'essai gratuit',
10
10
  restore: 'Restaurer les achats',
11
+ privacyPolicy: 'Politique de Confidentialité',
12
+ termsOfUse: "Conditions d'Utilisation",
11
13
  monthly: 'Mensuel',
12
14
  yearly: 'Annuel',
13
15
  lifetime: 'A vie',
@@ -8,6 +8,8 @@ export var subscriptionHI = {
8
8
  cta: 'Jaree rakhen',
9
9
  ctaTrial: 'Nishulk pareekshan shuru karen',
10
10
  restore: 'Khareedaaree punastaapeet karen',
11
+ privacyPolicy: 'गोपनीयता नीति',
12
+ termsOfUse: 'उपयोग की शर्तें',
11
13
  monthly: 'Maaseek',
12
14
  yearly: 'Vaarshik',
13
15
  lifetime: 'Aajeevon',
@@ -8,6 +8,8 @@ export var subscriptionHU = {
8
8
  cta: 'Folytatas',
9
9
  ctaTrial: 'Ingyenes proba inditasa',
10
10
  restore: 'Vasarlasok visszaallitasa',
11
+ privacyPolicy: 'Adatvédelmi irányelvek',
12
+ termsOfUse: 'Felhasználási feltételek',
11
13
  monthly: 'Havi',
12
14
  yearly: 'Eves',
13
15
  lifetime: 'Elettartam',
@@ -8,6 +8,8 @@ export var subscriptionID = {
8
8
  cta: 'Lanjutkan',
9
9
  ctaTrial: 'Mulai uji coba gratis',
10
10
  restore: 'Pulihkan pembelian',
11
+ privacyPolicy: 'Kebijakan Privasi',
12
+ termsOfUse: 'Ketentuan Penggunaan',
11
13
  monthly: 'Bulanan',
12
14
  yearly: 'Tahunan',
13
15
  lifetime: 'Seumur hidup',
@@ -8,6 +8,8 @@ export var subscriptionIT = {
8
8
  cta: 'Continua',
9
9
  ctaTrial: 'Inizia la prova gratuita',
10
10
  restore: 'Ripristina acquisti',
11
+ privacyPolicy: 'Informativa sulla Privacy',
12
+ termsOfUse: 'Termini di Utilizzo',
11
13
  monthly: 'Mensile',
12
14
  yearly: 'Annuale',
13
15
  lifetime: 'A vita',
@@ -8,6 +8,8 @@ export var subscriptionJA = {
8
8
  cta: '続ける',
9
9
  ctaTrial: '無料トライアルを開始',
10
10
  restore: '購入を復元',
11
+ privacyPolicy: 'プライバシーポリシー',
12
+ termsOfUse: '利用規約',
11
13
  monthly: '月額',
12
14
  yearly: '年額',
13
15
  lifetime: '買い切り',
@@ -8,6 +8,8 @@ export var subscriptionKO = {
8
8
  cta: '계속',
9
9
  ctaTrial: '무료 체험 시작',
10
10
  restore: '구매 복원',
11
+ privacyPolicy: '개인정보 처리방침',
12
+ termsOfUse: '이용약관',
11
13
  monthly: '월간',
12
14
  yearly: '연간',
13
15
  lifetime: '평생',
@@ -8,6 +8,8 @@ export var subscriptionNL = {
8
8
  cta: 'Doorgaan',
9
9
  ctaTrial: 'Start gratis proefperiode',
10
10
  restore: 'Aankopen herstellen',
11
+ privacyPolicy: 'Privacybeleid',
12
+ termsOfUse: 'Gebruiksvoorwaarden',
11
13
  monthly: 'Maandelijks',
12
14
  yearly: 'Jaarlijks',
13
15
  lifetime: 'Levenslang',
@@ -8,6 +8,8 @@ export var subscriptionNO = {
8
8
  cta: 'Fortsett',
9
9
  ctaTrial: 'Start gratis prøveperiode',
10
10
  restore: 'Gjenopprett kjøp',
11
+ privacyPolicy: 'Personvernerklæring',
12
+ termsOfUse: 'Bruksvilkår',
11
13
  monthly: 'Månedlig',
12
14
  yearly: 'Årlig',
13
15
  lifetime: 'Livstid',
@@ -8,6 +8,8 @@ export var subscriptionPL = {
8
8
  cta: 'Kontynuuj',
9
9
  ctaTrial: 'Rozpocznij bezpłatny okres próbny',
10
10
  restore: 'Przywróć zakupy',
11
+ privacyPolicy: 'Polityka Prywatności',
12
+ termsOfUse: 'Warunki Użytkowania',
11
13
  monthly: 'Miesięcznie',
12
14
  yearly: 'Rocznie',
13
15
  lifetime: 'Dożywotnio',
@@ -8,6 +8,8 @@ export var subscriptionPT = {
8
8
  cta: 'Continuar',
9
9
  ctaTrial: 'Iniciar teste gratuito',
10
10
  restore: 'Restaurar compras',
11
+ privacyPolicy: 'Política de Privacidade',
12
+ termsOfUse: 'Termos de Uso',
11
13
  monthly: 'Mensal',
12
14
  yearly: 'Anual',
13
15
  lifetime: 'Vitalício',
@@ -8,6 +8,8 @@ export var subscriptionRO = {
8
8
  cta: 'Continuă',
9
9
  ctaTrial: 'Începe perioada de probă gratuită',
10
10
  restore: 'Restaurează achizițiile',
11
+ privacyPolicy: 'Politica de Confidențialitate',
12
+ termsOfUse: 'Termeni de Utilizare',
11
13
  monthly: 'Lunar',
12
14
  yearly: 'Anual',
13
15
  lifetime: 'Pe viață',
@@ -8,6 +8,8 @@ export var subscriptionRU = {
8
8
  cta: 'Продолжить',
9
9
  ctaTrial: 'Начать бесплатный пробный период',
10
10
  restore: 'Восстановить покупки',
11
+ privacyPolicy: 'Политика конфиденциальности',
12
+ termsOfUse: 'Условия использования',
11
13
  monthly: 'Ежемесячно',
12
14
  yearly: 'Ежегодно',
13
15
  lifetime: 'Навсегда',
@@ -8,6 +8,8 @@ export var subscriptionSV = {
8
8
  cta: 'Fortsätt',
9
9
  ctaTrial: 'Starta gratis provperiod',
10
10
  restore: 'Återställ köp',
11
+ privacyPolicy: 'Integritetspolicy',
12
+ termsOfUse: 'Användarvillkor',
11
13
  monthly: 'Månadsvis',
12
14
  yearly: 'Årsvis',
13
15
  lifetime: 'Livstid',
@@ -8,6 +8,8 @@ export var subscriptionTH = {
8
8
  cta: 'ดำเนินการต่อ',
9
9
  ctaTrial: 'เริ่มทดลองใช้ฟรี',
10
10
  restore: 'กู้คืนการซื้อ',
11
+ privacyPolicy: 'นโยบายความเป็นส่วนตัว',
12
+ termsOfUse: 'ข้อกำหนดการใช้งาน',
11
13
  monthly: 'รายเดือน',
12
14
  yearly: 'รายปี',
13
15
  lifetime: 'ตลอดชีพ',
@@ -8,6 +8,8 @@ export var subscriptionTR = {
8
8
  cta: 'Devam et',
9
9
  ctaTrial: 'Ücretsiz denemeyi başlat',
10
10
  restore: 'Satın alımları geri yükle',
11
+ privacyPolicy: 'Gizlilik Politikası',
12
+ termsOfUse: 'Kullanım Koşulları',
11
13
  monthly: 'Aylık',
12
14
  yearly: 'Yıllık',
13
15
  lifetime: 'Ömür boyu',
@@ -8,6 +8,8 @@ export var subscriptionUK = {
8
8
  cta: 'Продовжити',
9
9
  ctaTrial: 'Почати безкоштовний пробний період',
10
10
  restore: 'Відновити покупки',
11
+ privacyPolicy: 'Політика конфіденційності',
12
+ termsOfUse: 'Умови використання',
11
13
  monthly: 'Щомісячно',
12
14
  yearly: 'Щорічно',
13
15
  lifetime: 'Назавжди',
@@ -8,6 +8,8 @@ export var subscriptionVI = {
8
8
  cta: 'Tiếp tục',
9
9
  ctaTrial: 'Bắt đầu dùng thử miễn phí',
10
10
  restore: 'Khôi phục giao dịch',
11
+ privacyPolicy: 'Chính sách Bảo mật',
12
+ termsOfUse: 'Điều khoản Sử dụng',
11
13
  monthly: 'Hàng tháng',
12
14
  yearly: 'Hàng năm',
13
15
  lifetime: 'Trọn đời',
@@ -8,6 +8,8 @@ export var subscriptionZH = {
8
8
  cta: '继续',
9
9
  ctaTrial: '开始免费试用',
10
10
  restore: '恢复购买',
11
+ privacyPolicy: '隐私政策',
12
+ termsOfUse: '使用条款',
11
13
  monthly: '月付',
12
14
  yearly: '年付',
13
15
  lifetime: '终身',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neko-os/rc-subscription",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "author": "Christian Storch <ccstorch@gmail.com>",
6
6
  "main": "dist/index.js",
package/src/config.js CHANGED
@@ -3,3 +3,9 @@ import { Platform } from 'react-native'
3
3
  export const RC_API_KEY =
4
4
  Platform.OS === 'ios' ? process.env.EXPO_PUBLIC_RC_API_KEY_IOS : process.env.EXPO_PUBLIC_RC_API_KEY_ANDROID
5
5
  export const RC_ENTITLEMENT_ID = process.env.EXPO_PUBLIC_RC_ENTITLEMENT_ID || 'premium'
6
+ export const PRIVACY_POLICY_URL = process.env.EXPO_PUBLIC_PRIVACY_POLICY_URL
7
+ export const TERMS_OF_USE_URL = process.env.EXPO_PUBLIC_TERMS_OF_USE_URL
8
+
9
+ // Route that renders ActiveSubscriptionView, which shows the Paywall when the
10
+ // user is not subscribed. Used to imperatively open the paywall.
11
+ export const SUBSCRIPTION_ROUTE = 'subscription/active'
@@ -1,7 +1,8 @@
1
- import React, { createContext, useContext, useEffect, useState } from 'react'
1
+ import React, { createContext, useCallback, useContext, useEffect, useState } from 'react'
2
2
  import Purchases from 'react-native-purchases'
3
+ import { useNavigation } from '@react-navigation/native'
3
4
 
4
- import { RC_API_KEY, RC_ENTITLEMENT_ID } from '../config'
5
+ import { RC_API_KEY, RC_ENTITLEMENT_ID, SUBSCRIPTION_ROUTE } from '../config'
5
6
 
6
7
  const SubscriptionContext = createContext({
7
8
  isSubscribed: false,
@@ -20,6 +21,55 @@ export function useIsSubscribed() {
20
21
  return useContext(SubscriptionContext).isSubscribed
21
22
  }
22
23
 
24
+ /**
25
+ * Returns an action wrapper that only runs when the user is subscribed,
26
+ * otherwise opens the paywall (navigates to `subscription/active`).
27
+ *
28
+ * Two equivalent call styles:
29
+ *
30
+ * const action = useSubscribedAction(fn) // bind the fn up front
31
+ * action(...args) // -> fn(...args) if subscribed
32
+ *
33
+ * const action = useSubscribedAction() // bind nothing
34
+ * action(fn, ...args) // -> fn(...args) if subscribed
35
+ *
36
+ * Returns the result of `fn` when subscribed, or `undefined` when the paywall
37
+ * is shown instead.
38
+ */
39
+ export function useSubscribedAction(boundFn) {
40
+ const { isSubscribed, isLoading } = useSubscription()
41
+ const { navigate } = useNavigation()
42
+
43
+ return useCallback(
44
+ (...args) => {
45
+ const fn = boundFn || args[0]
46
+ const fnArgs = boundFn ? args : args.slice(1)
47
+
48
+ if (typeof fn !== 'function') {
49
+ if (__DEV__) {
50
+ console.warn(
51
+ '[neko-rc-subscription] useSubscribedAction: no function to run — ' +
52
+ 'pass it to the hook `useSubscribedAction(fn)` or to the action `action(fn)`.',
53
+ )
54
+ }
55
+ return undefined
56
+ }
57
+
58
+ // Subscription state not resolved yet: no-op rather than wrongly bouncing
59
+ // an already-subscribed user to the paywall.
60
+ if (isLoading) return undefined
61
+
62
+ if (!isSubscribed) {
63
+ navigate(SUBSCRIPTION_ROUTE)
64
+ return undefined
65
+ }
66
+
67
+ return fn(...fnArgs)
68
+ },
69
+ [isSubscribed, isLoading, navigate, boundFn],
70
+ )
71
+ }
72
+
23
73
  export default function SubscriptionHandler({ children, paywallConfig }) {
24
74
  const [isSubscribed, setIsSubscribed] = useState(false)
25
75
  const [isLoading, setIsLoading] = useState(true)
@@ -1,6 +1,7 @@
1
1
  import { BlurView, Button, View, useTranslation } from '@neko-os/ui'
2
2
  import { useNavigation } from '@react-navigation/native'
3
3
 
4
+ import { SUBSCRIPTION_ROUTE } from '../config'
4
5
  import { useIsSubscribed } from './SubscriptionHandler'
5
6
 
6
7
  export default function SubscriptionRequiredCTA({
@@ -20,7 +21,7 @@ export default function SubscriptionRequiredCTA({
20
21
  return (
21
22
  <View relative hiddenOverflow {...props}>
22
23
  {children}
23
- <BlurView absoluteFill center zIndex={10} intensity={18} onPress={() => navigate('subscription/active')}>
24
+ <BlurView absoluteFill center zIndex={10} intensity={18} onPress={() => navigate(SUBSCRIPTION_ROUTE)}>
24
25
  {!hideButton && (
25
26
  <Button
26
27
  label={t('cta.unlock')}
@@ -28,7 +29,7 @@ export default function SubscriptionRequiredCTA({
28
29
  yellow
29
30
  size={size || 'xs'}
30
31
  {...buttonProps}
31
- onPress={() => navigate('subscription/active')}
32
+ onPress={() => navigate(SUBSCRIPTION_ROUTE)}
32
33
  />
33
34
  )}
34
35
  </BlurView>
@@ -1,16 +1,20 @@
1
1
  import {
2
2
  AnimatedTopBar,
3
3
  BlurView,
4
+ Link,
4
5
  ReanimatedScrollHandler,
5
6
  ScrollView,
7
+ Text,
6
8
  View,
7
9
  useReanimatedScroll,
8
10
  useTranslation,
9
11
  } from '@neko-os/ui'
10
- import { Platform } from 'react-native'
12
+ import { Linking, Platform } from 'react-native'
11
13
  import { useState } from 'react'
12
14
  import Animated from 'react-native-reanimated'
13
15
 
16
+ import { PRIVACY_POLICY_URL, TERMS_OF_USE_URL } from '../../config'
17
+
14
18
  import { useSubscription } from '../SubscriptionHandler'
15
19
  import PaywallFeatures from './PaywallFeatures'
16
20
  import PaywallFooter from './PaywallFooter'
@@ -38,6 +42,26 @@ function getTrialDays(pkg) {
38
42
  return units
39
43
  }
40
44
 
45
+ function PaywallLegalLinks({ t }) {
46
+ if (!PRIVACY_POLICY_URL && !TERMS_OF_USE_URL) return null
47
+
48
+ return (
49
+ <View row center gap="xs" paddingV="md">
50
+ {PRIVACY_POLICY_URL && (
51
+ <Link onPress={() => Linking.openURL(PRIVACY_POLICY_URL)}>
52
+ <Text xs text3 underline>{t('paywall.privacyPolicy')}</Text>
53
+ </Link>
54
+ )}
55
+ {PRIVACY_POLICY_URL && TERMS_OF_USE_URL && <Text xs text4>·</Text>}
56
+ {TERMS_OF_USE_URL && (
57
+ <Link onPress={() => Linking.openURL(TERMS_OF_USE_URL)}>
58
+ <Text xs text3 underline>{t('paywall.termsOfUse')}</Text>
59
+ </Link>
60
+ )}
61
+ </View>
62
+ )
63
+ }
64
+
41
65
  function PaywallScrollContent({
42
66
  image,
43
67
  title,
@@ -49,6 +73,7 @@ function PaywallScrollContent({
49
73
  monthlyPrice,
50
74
  showReturnIcon,
51
75
  modal,
76
+ t,
52
77
  }) {
53
78
  const { scrollHandler } = useReanimatedScroll()
54
79
 
@@ -68,6 +93,7 @@ function PaywallScrollContent({
68
93
  />
69
94
  ))}
70
95
  </View>
96
+ <PaywallLegalLinks t={t} />
71
97
  <View height={200} />
72
98
  </AnimatedScrollView>
73
99
  )
@@ -115,6 +141,7 @@ export default function Paywall({ modal, showReturn, footerPaddingB }) {
115
141
  monthlyPrice={monthlyPrice}
116
142
  showReturnIcon={showReturnIcon}
117
143
  modal={modal}
144
+ t={t}
118
145
  />
119
146
  </ReanimatedScrollHandler>
120
147
 
package/src/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { registerSubscriptionLocales } from './locales/index'
2
- export { default as SubscriptionHandler, useIsSubscribed, useSubscription } from './containers/SubscriptionHandler'
2
+ export { default as SubscriptionHandler, useIsSubscribed, useSubscribedAction, useSubscription } from './containers/SubscriptionHandler'
3
3
  export { default as SubscriptionRequired } from './containers/SubscriptionRequired'
4
4
  export { default as SubscriptionRequiredCTA } from './containers/SubscriptionRequiredCTA'
5
5
  export { default as Paywall } from './containers/paywall/Paywall'
package/src/locales/cs.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionCS = {
8
8
  cta: 'Pokracovat',
9
9
  ctaTrial: 'Zahajit zkusebni obdobi',
10
10
  restore: 'Obnovit nakupy',
11
+ privacyPolicy: 'Zásady ochrany osobních údajů',
12
+ termsOfUse: 'Podmínky použití',
11
13
  monthly: 'Mesicne',
12
14
  yearly: 'Rocne',
13
15
  lifetime: 'Dozivotne',
package/src/locales/da.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionDA = {
8
8
  cta: 'Fortsaet',
9
9
  ctaTrial: 'Start gratis proveperiode',
10
10
  restore: 'Gendan kob',
11
+ privacyPolicy: 'Privatlivspolitik',
12
+ termsOfUse: 'Brugsvilkår',
11
13
  monthly: 'Manedligt',
12
14
  yearly: 'Arligt',
13
15
  lifetime: 'Livstid',
package/src/locales/de.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionDE = {
8
8
  cta: 'Weiter',
9
9
  ctaTrial: 'Kostenlos testen',
10
10
  restore: 'Kaeufe wiederherstellen',
11
+ privacyPolicy: 'Datenschutzerklärung',
12
+ termsOfUse: 'Nutzungsbedingungen',
11
13
  monthly: 'Monatlich',
12
14
  yearly: 'Jaehrlich',
13
15
  lifetime: 'Lebenslang',
package/src/locales/el.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionEL = {
8
8
  cta: 'Synecheia',
9
9
  ctaTrial: 'Enarxi dorean dokimis',
10
10
  restore: 'Epanafora agoron',
11
+ privacyPolicy: 'Πολιτική Απορρήτου',
12
+ termsOfUse: 'Όροι Χρήσης',
11
13
  monthly: 'Miniaia',
12
14
  yearly: 'Etisia',
13
15
  lifetime: 'Dia viou',
package/src/locales/en.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionEN = {
8
8
  cta: 'Continue',
9
9
  ctaTrial: 'Start free trial',
10
10
  restore: 'Restore purchases',
11
+ privacyPolicy: 'Privacy Policy',
12
+ termsOfUse: 'Terms of Use',
11
13
  monthly: 'Monthly',
12
14
  yearly: 'Yearly',
13
15
  lifetime: 'Lifetime',
package/src/locales/es.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionES = {
8
8
  cta: 'Continuar',
9
9
  ctaTrial: 'Iniciar prueba gratuita',
10
10
  restore: 'Restaurar compras',
11
+ privacyPolicy: 'Política de Privacidad',
12
+ termsOfUse: 'Términos de Uso',
11
13
  monthly: 'Mensual',
12
14
  yearly: 'Anual',
13
15
  lifetime: 'De por vida',
package/src/locales/fi.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionFI = {
8
8
  cta: 'Jatka',
9
9
  ctaTrial: 'Aloita ilmainen kokeilu',
10
10
  restore: 'Palauta ostokset',
11
+ privacyPolicy: 'Tietosuojakäytäntö',
12
+ termsOfUse: 'Käyttöehdot',
11
13
  monthly: 'Kuukausittain',
12
14
  yearly: 'Vuosittain',
13
15
  lifetime: 'Elinaika',
package/src/locales/fr.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionFR = {
8
8
  cta: 'Continuer',
9
9
  ctaTrial: 'Demarrer l\'essai gratuit',
10
10
  restore: 'Restaurer les achats',
11
+ privacyPolicy: 'Politique de Confidentialité',
12
+ termsOfUse: "Conditions d'Utilisation",
11
13
  monthly: 'Mensuel',
12
14
  yearly: 'Annuel',
13
15
  lifetime: 'A vie',
package/src/locales/hi.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionHI = {
8
8
  cta: 'Jaree rakhen',
9
9
  ctaTrial: 'Nishulk pareekshan shuru karen',
10
10
  restore: 'Khareedaaree punastaapeet karen',
11
+ privacyPolicy: 'गोपनीयता नीति',
12
+ termsOfUse: 'उपयोग की शर्तें',
11
13
  monthly: 'Maaseek',
12
14
  yearly: 'Vaarshik',
13
15
  lifetime: 'Aajeevon',
package/src/locales/hu.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionHU = {
8
8
  cta: 'Folytatas',
9
9
  ctaTrial: 'Ingyenes proba inditasa',
10
10
  restore: 'Vasarlasok visszaallitasa',
11
+ privacyPolicy: 'Adatvédelmi irányelvek',
12
+ termsOfUse: 'Felhasználási feltételek',
11
13
  monthly: 'Havi',
12
14
  yearly: 'Eves',
13
15
  lifetime: 'Elettartam',
package/src/locales/id.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionID = {
8
8
  cta: 'Lanjutkan',
9
9
  ctaTrial: 'Mulai uji coba gratis',
10
10
  restore: 'Pulihkan pembelian',
11
+ privacyPolicy: 'Kebijakan Privasi',
12
+ termsOfUse: 'Ketentuan Penggunaan',
11
13
  monthly: 'Bulanan',
12
14
  yearly: 'Tahunan',
13
15
  lifetime: 'Seumur hidup',
package/src/locales/it.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionIT = {
8
8
  cta: 'Continua',
9
9
  ctaTrial: 'Inizia la prova gratuita',
10
10
  restore: 'Ripristina acquisti',
11
+ privacyPolicy: 'Informativa sulla Privacy',
12
+ termsOfUse: 'Termini di Utilizzo',
11
13
  monthly: 'Mensile',
12
14
  yearly: 'Annuale',
13
15
  lifetime: 'A vita',
package/src/locales/ja.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionJA = {
8
8
  cta: '続ける',
9
9
  ctaTrial: '無料トライアルを開始',
10
10
  restore: '購入を復元',
11
+ privacyPolicy: 'プライバシーポリシー',
12
+ termsOfUse: '利用規約',
11
13
  monthly: '月額',
12
14
  yearly: '年額',
13
15
  lifetime: '買い切り',
package/src/locales/ko.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionKO = {
8
8
  cta: '계속',
9
9
  ctaTrial: '무료 체험 시작',
10
10
  restore: '구매 복원',
11
+ privacyPolicy: '개인정보 처리방침',
12
+ termsOfUse: '이용약관',
11
13
  monthly: '월간',
12
14
  yearly: '연간',
13
15
  lifetime: '평생',
package/src/locales/nl.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionNL = {
8
8
  cta: 'Doorgaan',
9
9
  ctaTrial: 'Start gratis proefperiode',
10
10
  restore: 'Aankopen herstellen',
11
+ privacyPolicy: 'Privacybeleid',
12
+ termsOfUse: 'Gebruiksvoorwaarden',
11
13
  monthly: 'Maandelijks',
12
14
  yearly: 'Jaarlijks',
13
15
  lifetime: 'Levenslang',
package/src/locales/no.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionNO = {
8
8
  cta: 'Fortsett',
9
9
  ctaTrial: 'Start gratis prøveperiode',
10
10
  restore: 'Gjenopprett kjøp',
11
+ privacyPolicy: 'Personvernerklæring',
12
+ termsOfUse: 'Bruksvilkår',
11
13
  monthly: 'Månedlig',
12
14
  yearly: 'Årlig',
13
15
  lifetime: 'Livstid',
package/src/locales/pl.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionPL = {
8
8
  cta: 'Kontynuuj',
9
9
  ctaTrial: 'Rozpocznij bezpłatny okres próbny',
10
10
  restore: 'Przywróć zakupy',
11
+ privacyPolicy: 'Polityka Prywatności',
12
+ termsOfUse: 'Warunki Użytkowania',
11
13
  monthly: 'Miesięcznie',
12
14
  yearly: 'Rocznie',
13
15
  lifetime: 'Dożywotnio',
package/src/locales/pt.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionPT = {
8
8
  cta: 'Continuar',
9
9
  ctaTrial: 'Iniciar teste gratuito',
10
10
  restore: 'Restaurar compras',
11
+ privacyPolicy: 'Política de Privacidade',
12
+ termsOfUse: 'Termos de Uso',
11
13
  monthly: 'Mensal',
12
14
  yearly: 'Anual',
13
15
  lifetime: 'Vitalício',
package/src/locales/ro.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionRO = {
8
8
  cta: 'Continuă',
9
9
  ctaTrial: 'Începe perioada de probă gratuită',
10
10
  restore: 'Restaurează achizițiile',
11
+ privacyPolicy: 'Politica de Confidențialitate',
12
+ termsOfUse: 'Termeni de Utilizare',
11
13
  monthly: 'Lunar',
12
14
  yearly: 'Anual',
13
15
  lifetime: 'Pe viață',
package/src/locales/ru.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionRU = {
8
8
  cta: 'Продолжить',
9
9
  ctaTrial: 'Начать бесплатный пробный период',
10
10
  restore: 'Восстановить покупки',
11
+ privacyPolicy: 'Политика конфиденциальности',
12
+ termsOfUse: 'Условия использования',
11
13
  monthly: 'Ежемесячно',
12
14
  yearly: 'Ежегодно',
13
15
  lifetime: 'Навсегда',
package/src/locales/sv.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionSV = {
8
8
  cta: 'Fortsätt',
9
9
  ctaTrial: 'Starta gratis provperiod',
10
10
  restore: 'Återställ köp',
11
+ privacyPolicy: 'Integritetspolicy',
12
+ termsOfUse: 'Användarvillkor',
11
13
  monthly: 'Månadsvis',
12
14
  yearly: 'Årsvis',
13
15
  lifetime: 'Livstid',
package/src/locales/th.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionTH = {
8
8
  cta: 'ดำเนินการต่อ',
9
9
  ctaTrial: 'เริ่มทดลองใช้ฟรี',
10
10
  restore: 'กู้คืนการซื้อ',
11
+ privacyPolicy: 'นโยบายความเป็นส่วนตัว',
12
+ termsOfUse: 'ข้อกำหนดการใช้งาน',
11
13
  monthly: 'รายเดือน',
12
14
  yearly: 'รายปี',
13
15
  lifetime: 'ตลอดชีพ',
package/src/locales/tr.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionTR = {
8
8
  cta: 'Devam et',
9
9
  ctaTrial: 'Ücretsiz denemeyi başlat',
10
10
  restore: 'Satın alımları geri yükle',
11
+ privacyPolicy: 'Gizlilik Politikası',
12
+ termsOfUse: 'Kullanım Koşulları',
11
13
  monthly: 'Aylık',
12
14
  yearly: 'Yıllık',
13
15
  lifetime: 'Ömür boyu',
package/src/locales/uk.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionUK = {
8
8
  cta: 'Продовжити',
9
9
  ctaTrial: 'Почати безкоштовний пробний період',
10
10
  restore: 'Відновити покупки',
11
+ privacyPolicy: 'Політика конфіденційності',
12
+ termsOfUse: 'Умови використання',
11
13
  monthly: 'Щомісячно',
12
14
  yearly: 'Щорічно',
13
15
  lifetime: 'Назавжди',
package/src/locales/vi.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionVI = {
8
8
  cta: 'Tiếp tục',
9
9
  ctaTrial: 'Bắt đầu dùng thử miễn phí',
10
10
  restore: 'Khôi phục giao dịch',
11
+ privacyPolicy: 'Chính sách Bảo mật',
12
+ termsOfUse: 'Điều khoản Sử dụng',
11
13
  monthly: 'Hàng tháng',
12
14
  yearly: 'Hàng năm',
13
15
  lifetime: 'Trọn đời',
package/src/locales/zh.js CHANGED
@@ -8,6 +8,8 @@ export const subscriptionZH = {
8
8
  cta: '继续',
9
9
  ctaTrial: '开始免费试用',
10
10
  restore: '恢复购买',
11
+ privacyPolicy: '隐私政策',
12
+ termsOfUse: '使用条款',
11
13
  monthly: '月付',
12
14
  yearly: '年付',
13
15
  lifetime: '终身',