@revenuecat/purchases-capacitor-ui 10.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.
- package/README.md +119 -0
- package/android/build.gradle +56 -0
- package/android/src/main/AndroidManifest.xml +9 -0
- package/android/src/main/java/com/revenuecat/purchases/capacitor/ui/RevenueCatUIPlugin.kt +154 -0
- package/dist/esm/definitions.d.ts +65 -0
- package/dist/esm/definitions.js +4 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +18 -0
- package/dist/esm/web.js +50 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.js +615 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Plugin/Plugin/RevenueCatUIPlugin.m +10 -0
- package/ios/Plugin/Plugin/RevenueCatUIPlugin.swift +159 -0
- package/package.json +84 -0
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# @revenuecat/purchases-capacitor-ui
|
|
2
|
+
|
|
3
|
+
UI components for RevenueCat Capacitor SDK. This plugin extends the functionality of the [@revenuecat/purchases-capacitor](https://github.com/RevenueCat/purchases-capacitor) plugin to provide UI components for displaying paywalls and customer center.
|
|
4
|
+
|
|
5
|
+
## Platform Support
|
|
6
|
+
|
|
7
|
+
> ⚠️ **IMPORTANT: Platform Limitations**
|
|
8
|
+
>
|
|
9
|
+
> - **iOS**: Paywalls and Customer Center are fully supported on iOS 15.0+
|
|
10
|
+
> - **Android**: Paywalls and Customer Center are now fully supported on Android 7.0+ (API level 24+)
|
|
11
|
+
> - **Web**: Not supported
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @revenuecat/purchases-capacitor
|
|
17
|
+
npm install @revenuecat/purchases-capacitor-ui
|
|
18
|
+
npx cap sync
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
> Note: Make sure to use the same version for both `@revenuecat/purchases-capacitor` and `@revenuecat/purchases-capacitor-ui`.
|
|
22
|
+
|
|
23
|
+
## iOS Configuration
|
|
24
|
+
|
|
25
|
+
For iOS, you need to add SwiftUI to your app's capabilities. Follow the [iOS SDK's SwiftUI Configuration](https://github.com/RevenueCat/purchases-ios-ui#swift-package-manager) guide for details.
|
|
26
|
+
|
|
27
|
+
## API
|
|
28
|
+
|
|
29
|
+
<docgen-index>
|
|
30
|
+
|
|
31
|
+
- [`presentPaywall(...)`](#presentpaywall)
|
|
32
|
+
- [`presentPaywallIfNeeded(...)`](#presentpaywallIfNeeded)
|
|
33
|
+
- [`presentCustomerCenter()`](#presentcustomercenter)
|
|
34
|
+
- [`addListener('paywallDisplayed', ...)`](#addlistenerpaywallDisplayed)
|
|
35
|
+
- [`addListener('paywallDismissed', ...)`](#addlistenerpaywallDismissed)
|
|
36
|
+
- [`removeAllListeners()`](#removealllisteners)
|
|
37
|
+
- [Interfaces](#interfaces)
|
|
38
|
+
- [Enums](#enums)
|
|
39
|
+
|
|
40
|
+
</docgen-index>
|
|
41
|
+
|
|
42
|
+
<docgen-api>
|
|
43
|
+
<!--Update with API docs-->
|
|
44
|
+
</docgen-api>
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
### Initialization
|
|
49
|
+
|
|
50
|
+
First, initialize the main RevenueCat SDK:
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { Purchases } from '@revenuecat/purchases-capacitor';
|
|
54
|
+
|
|
55
|
+
// Initialize the SDK
|
|
56
|
+
await Purchases.configure({
|
|
57
|
+
apiKey: 'your_api_key',
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Presenting Paywalls
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { RevenueCatUI } from '@revenuecat/purchases-capacitor-ui';
|
|
65
|
+
|
|
66
|
+
// Present a paywall with the default offering
|
|
67
|
+
const result = await RevenueCatUI.presentPaywall();
|
|
68
|
+
|
|
69
|
+
// Present a paywall with a specific offering
|
|
70
|
+
const result = await RevenueCatUI.presentPaywall({
|
|
71
|
+
offeringIdentifier: 'premium',
|
|
72
|
+
displayCloseButton: true,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Present a paywall only if the user doesn't have a specific entitlement
|
|
76
|
+
const result = await RevenueCatUI.presentPaywallIfNeeded({
|
|
77
|
+
requiredEntitlementIdentifier: 'pro_access',
|
|
78
|
+
offeringIdentifier: 'premium',
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Customer Center
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { RevenueCatUI } from '@revenuecat/purchases-capacitor-ui';
|
|
86
|
+
|
|
87
|
+
// Present the customer center
|
|
88
|
+
await RevenueCatUI.presentCustomerCenter();
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Demo
|
|
92
|
+
|
|
93
|
+
Here's a quick demo of Paywalls running on iOS:
|
|
94
|
+
|
|
95
|
+

|
|
96
|
+
|
|
97
|
+
> Note: To view the demo, please download the MP4 file from the assets directory.
|
|
98
|
+
|
|
99
|
+
## Events
|
|
100
|
+
|
|
101
|
+
You can listen for paywall events:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { RevenueCatUI } from '@revenuecat/purchases-capacitor-ui';
|
|
105
|
+
|
|
106
|
+
// Listen for when a paywall is displayed
|
|
107
|
+
RevenueCatUI.addListener('paywallDisplayed', () => {
|
|
108
|
+
console.log('Paywall displayed');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Listen for when a paywall is dismissed
|
|
112
|
+
RevenueCatUI.addListener('paywallDismissed', () => {
|
|
113
|
+
console.log('Paywall dismissed');
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## License
|
|
118
|
+
|
|
119
|
+
MIT
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
ext {
|
|
2
|
+
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.4.2'
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
buildscript {
|
|
6
|
+
repositories {
|
|
7
|
+
google()
|
|
8
|
+
mavenCentral()
|
|
9
|
+
}
|
|
10
|
+
dependencies {
|
|
11
|
+
classpath 'com.android.tools.build:gradle:7.2.1'
|
|
12
|
+
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20'
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
apply plugin: 'com.android.library'
|
|
17
|
+
apply plugin: 'org.jetbrains.kotlin.android'
|
|
18
|
+
|
|
19
|
+
android {
|
|
20
|
+
namespace "com.revenuecat.purchases.capacitor.ui"
|
|
21
|
+
compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
|
|
22
|
+
defaultConfig {
|
|
23
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 24
|
|
24
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
|
|
25
|
+
versionCode 1
|
|
26
|
+
versionName "1.0"
|
|
27
|
+
}
|
|
28
|
+
buildTypes {
|
|
29
|
+
release {
|
|
30
|
+
minifyEnabled false
|
|
31
|
+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
lintOptions {
|
|
35
|
+
abortOnError false
|
|
36
|
+
}
|
|
37
|
+
compileOptions {
|
|
38
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
39
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
40
|
+
}
|
|
41
|
+
kotlinOptions {
|
|
42
|
+
jvmTarget = '1.8'
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
repositories {
|
|
47
|
+
google()
|
|
48
|
+
mavenCentral()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
dependencies {
|
|
52
|
+
implementation project(':capacitor-android')
|
|
53
|
+
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
54
|
+
implementation 'com.revenuecat.purchases:purchases-hybrid-common-ui:13.32.0'
|
|
55
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.8.20"
|
|
56
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
+
package="com.revenuecat.purchases.capacitor.ui">
|
|
4
|
+
|
|
5
|
+
<application>
|
|
6
|
+
<!-- No specific activities need to be declared here since they are included in the 'purchases-ui' library -->
|
|
7
|
+
</application>
|
|
8
|
+
|
|
9
|
+
</manifest>
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
package com.revenuecat.purchases.capacitor.ui
|
|
2
|
+
|
|
3
|
+
import android.content.Intent
|
|
4
|
+
import androidx.activity.result.ActivityResultLauncher
|
|
5
|
+
import androidx.activity.result.contract.ActivityResultContracts
|
|
6
|
+
import androidx.fragment.app.FragmentActivity
|
|
7
|
+
import com.getcapacitor.JSObject
|
|
8
|
+
import com.getcapacitor.Plugin
|
|
9
|
+
import com.getcapacitor.PluginCall
|
|
10
|
+
import com.getcapacitor.PluginMethod
|
|
11
|
+
import com.getcapacitor.annotation.CapacitorPlugin
|
|
12
|
+
import com.revenuecat.purchases.hybridcommon.ui.PaywallResultListener
|
|
13
|
+
import com.revenuecat.purchases.hybridcommon.ui.PaywallSource
|
|
14
|
+
import com.revenuecat.purchases.hybridcommon.ui.PresentPaywallOptions
|
|
15
|
+
import com.revenuecat.purchases.hybridcommon.ui.presentPaywallFromFragment
|
|
16
|
+
import com.revenuecat.purchases.ui.revenuecatui.customercenter.ShowCustomerCenter
|
|
17
|
+
|
|
18
|
+
@CapacitorPlugin(name = "RevenueCatUI")
|
|
19
|
+
class RevenueCatUIPlugin : Plugin(), PaywallResultListener {
|
|
20
|
+
|
|
21
|
+
private var savedCall: PluginCall? = null
|
|
22
|
+
private var customerCenterLauncher: ActivityResultLauncher<Intent>? = null
|
|
23
|
+
|
|
24
|
+
override fun load() {
|
|
25
|
+
super.load()
|
|
26
|
+
|
|
27
|
+
// Register an ActivityResultLauncher for the Customer Center flow
|
|
28
|
+
customerCenterLauncher = activity.registerForActivityResult(
|
|
29
|
+
ActivityResultContracts.StartActivityForResult()
|
|
30
|
+
) {
|
|
31
|
+
// Regardless of the result we just resolve the call
|
|
32
|
+
savedCall?.resolve()
|
|
33
|
+
savedCall = null
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@PluginMethod
|
|
38
|
+
fun presentPaywall(call: PluginCall) {
|
|
39
|
+
val offering = call.getObject("offering")
|
|
40
|
+
val offeringIdentifier = offering?.getString("identifier")
|
|
41
|
+
val displayCloseButton = call.getBoolean("displayCloseButton") ?: false
|
|
42
|
+
|
|
43
|
+
presentPaywallInternal(
|
|
44
|
+
call = call,
|
|
45
|
+
offeringIdentifier = offeringIdentifier,
|
|
46
|
+
displayCloseButton = displayCloseButton,
|
|
47
|
+
requiredEntitlementIdentifier = null
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@PluginMethod
|
|
52
|
+
fun presentPaywallIfNeeded(call: PluginCall) {
|
|
53
|
+
val requiredEntitlementIdentifier = call.getString("requiredEntitlementIdentifier")
|
|
54
|
+
if (requiredEntitlementIdentifier.isNullOrEmpty()) {
|
|
55
|
+
call.reject(
|
|
56
|
+
"PAYWALL_ERROR",
|
|
57
|
+
"Required entitlement identifier is required"
|
|
58
|
+
)
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
val offering = call.getObject("offering")
|
|
63
|
+
val offeringIdentifier = offering?.getString("identifier")
|
|
64
|
+
val displayCloseButton = call.getBoolean("displayCloseButton") ?: false
|
|
65
|
+
|
|
66
|
+
presentPaywallInternal(
|
|
67
|
+
call = call,
|
|
68
|
+
offeringIdentifier = offeringIdentifier,
|
|
69
|
+
displayCloseButton = displayCloseButton,
|
|
70
|
+
requiredEntitlementIdentifier = requiredEntitlementIdentifier
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Shared implementation for presenting a paywall
|
|
76
|
+
*/
|
|
77
|
+
private fun presentPaywallInternal(
|
|
78
|
+
call: PluginCall,
|
|
79
|
+
offeringIdentifier: String?,
|
|
80
|
+
displayCloseButton: Boolean,
|
|
81
|
+
requiredEntitlementIdentifier: String?
|
|
82
|
+
) {
|
|
83
|
+
// Check if there's already a presentation in progress
|
|
84
|
+
if (savedCall != null) {
|
|
85
|
+
call.reject(
|
|
86
|
+
"PAYWALL_ERROR",
|
|
87
|
+
"A paywall presentation is already in progress"
|
|
88
|
+
)
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
savedCall = call
|
|
93
|
+
|
|
94
|
+
val currentActivity = activity
|
|
95
|
+
if (currentActivity !is FragmentActivity) {
|
|
96
|
+
call.reject(
|
|
97
|
+
"PAYWALL_ERROR",
|
|
98
|
+
"Paywalls require your activity to subclass FragmentActivity"
|
|
99
|
+
)
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
val paywallSource = offeringIdentifier?.let { PaywallSource.OfferingIdentifier(it) }
|
|
104
|
+
?: PaywallSource.DefaultOffering
|
|
105
|
+
|
|
106
|
+
val options = PresentPaywallOptions(
|
|
107
|
+
paywallSource = paywallSource,
|
|
108
|
+
requiredEntitlementIdentifier = requiredEntitlementIdentifier,
|
|
109
|
+
shouldDisplayDismissButton = displayCloseButton,
|
|
110
|
+
paywallResultListener = this
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
presentPaywallFromFragment(currentActivity, options)
|
|
114
|
+
notifyListeners("paywallDisplayed", JSObject())
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@PluginMethod
|
|
118
|
+
fun presentCustomerCenter(call: PluginCall) {
|
|
119
|
+
val currentActivity = activity
|
|
120
|
+
if (currentActivity == null) {
|
|
121
|
+
call.reject(
|
|
122
|
+
"CUSTOMER_CENTER_ERROR",
|
|
123
|
+
"Could not present Customer Center. There's no activity"
|
|
124
|
+
)
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Check if there's already a presentation in progress
|
|
129
|
+
if (savedCall != null) {
|
|
130
|
+
call.reject(
|
|
131
|
+
"CUSTOMER_CENTER_ERROR",
|
|
132
|
+
"A customer center presentation is already in progress"
|
|
133
|
+
)
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
savedCall = call
|
|
138
|
+
|
|
139
|
+
val intent = ShowCustomerCenter().createIntent(currentActivity, Unit)
|
|
140
|
+
customerCenterLauncher?.launch(intent)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// region PaywallResultListener
|
|
144
|
+
override fun onPaywallResult(paywallResult: String) {
|
|
145
|
+
val jsObject = JSObject().apply {
|
|
146
|
+
put("result", paywallResult)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
savedCall?.resolve(jsObject)
|
|
150
|
+
notifyListeners("paywallDismissed", JSObject())
|
|
151
|
+
savedCall = null
|
|
152
|
+
}
|
|
153
|
+
// endregion
|
|
154
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { PluginListenerHandle } from '@capacitor/core';
|
|
2
|
+
import type { PurchasesOffering } from '@revenuecat/purchases-typescript-internal-esm';
|
|
3
|
+
import { PAYWALL_RESULT } from '@revenuecat/purchases-typescript-internal-esm';
|
|
4
|
+
export interface RevenueCatUIPlugin {
|
|
5
|
+
/**
|
|
6
|
+
* Presents a paywall configured in the RevenueCat dashboard.
|
|
7
|
+
* @param options The options for presenting the paywall.
|
|
8
|
+
* @returns A PaywallResult indicating what happened during the paywall presentation.
|
|
9
|
+
*/
|
|
10
|
+
presentPaywall(options?: PresentPaywallOptions): Promise<PaywallResult>;
|
|
11
|
+
/**
|
|
12
|
+
* Presents a paywall only if the user does not have the specified entitlement.
|
|
13
|
+
* @param options The options for presenting the paywall if needed.
|
|
14
|
+
* @returns A PaywallResult indicating what happened during the paywall presentation.
|
|
15
|
+
*/
|
|
16
|
+
presentPaywallIfNeeded(options: PresentPaywallIfNeededOptions): Promise<PaywallResult>;
|
|
17
|
+
/**
|
|
18
|
+
* Presents the customer center where users can manage their subscriptions.
|
|
19
|
+
*/
|
|
20
|
+
presentCustomerCenter(): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Used for web only. Enables or disables returning mock results instead of rejecting promises with "not supported".
|
|
23
|
+
* For testing purposes only.
|
|
24
|
+
* @param options Options for mock web results
|
|
25
|
+
*/
|
|
26
|
+
setMockWebResults?(options: {
|
|
27
|
+
shouldMockWebResults: boolean;
|
|
28
|
+
}): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Listen for when a paywall is displayed or dismissed.
|
|
31
|
+
* @param eventName The event to listen for
|
|
32
|
+
* @param listener The listener to call when the event is triggered
|
|
33
|
+
*/
|
|
34
|
+
addListener(eventName: 'paywallDisplayed' | 'paywallDismissed', listener: () => void): Promise<PluginListenerHandle>;
|
|
35
|
+
/**
|
|
36
|
+
* Remove all listeners for this plugin.
|
|
37
|
+
*/
|
|
38
|
+
removeAllListeners(): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export interface PresentPaywallOptions {
|
|
41
|
+
/**
|
|
42
|
+
* The offering to present.
|
|
43
|
+
* If not provided, the current offering will be used.
|
|
44
|
+
*/
|
|
45
|
+
offering?: PurchasesOffering;
|
|
46
|
+
/**
|
|
47
|
+
* Whether to display a close button on the paywall.
|
|
48
|
+
* Only applicable for original template paywalls, ignored for V2 Paywalls.
|
|
49
|
+
*/
|
|
50
|
+
displayCloseButton?: boolean;
|
|
51
|
+
}
|
|
52
|
+
export interface PresentPaywallIfNeededOptions extends PresentPaywallOptions {
|
|
53
|
+
/**
|
|
54
|
+
* The identifier of the entitlement that is required.
|
|
55
|
+
* The paywall will only be presented if the user doesn't have this entitlement.
|
|
56
|
+
*/
|
|
57
|
+
requiredEntitlementIdentifier: string;
|
|
58
|
+
}
|
|
59
|
+
export { PAYWALL_RESULT as PaywallResultEnum };
|
|
60
|
+
export interface PaywallResult {
|
|
61
|
+
/**
|
|
62
|
+
* The result of the paywall presentation.
|
|
63
|
+
*/
|
|
64
|
+
result: PAYWALL_RESULT;
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAgE/E,oFAAoF;AACpF,OAAO,EAAE,cAAc,IAAI,iBAAiB,EAAE,CAAC","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\nimport type { PurchasesOffering } from '@revenuecat/purchases-typescript-internal-esm';\nimport { PAYWALL_RESULT } from '@revenuecat/purchases-typescript-internal-esm';\n\nexport interface RevenueCatUIPlugin {\n /**\n * Presents a paywall configured in the RevenueCat dashboard.\n * @param options The options for presenting the paywall.\n * @returns A PaywallResult indicating what happened during the paywall presentation.\n */\n presentPaywall(options?: PresentPaywallOptions): Promise<PaywallResult>;\n\n /**\n * Presents a paywall only if the user does not have the specified entitlement.\n * @param options The options for presenting the paywall if needed.\n * @returns A PaywallResult indicating what happened during the paywall presentation.\n */\n presentPaywallIfNeeded(options: PresentPaywallIfNeededOptions): Promise<PaywallResult>;\n\n /**\n * Presents the customer center where users can manage their subscriptions.\n */\n presentCustomerCenter(): Promise<void>;\n\n /**\n * Used for web only. Enables or disables returning mock results instead of rejecting promises with \"not supported\".\n * For testing purposes only.\n * @param options Options for mock web results\n */\n setMockWebResults?(options: { shouldMockWebResults: boolean }): Promise<void>;\n\n /**\n * Listen for when a paywall is displayed or dismissed.\n * @param eventName The event to listen for\n * @param listener The listener to call when the event is triggered\n */\n addListener(eventName: 'paywallDisplayed' | 'paywallDismissed', listener: () => void): Promise<PluginListenerHandle>;\n\n /**\n * Remove all listeners for this plugin.\n */\n removeAllListeners(): Promise<void>;\n}\n\nexport interface PresentPaywallOptions {\n /**\n * The offering to present.\n * If not provided, the current offering will be used.\n */\n offering?: PurchasesOffering;\n\n /**\n * Whether to display a close button on the paywall.\n * Only applicable for original template paywalls, ignored for V2 Paywalls.\n */\n displayCloseButton?: boolean;\n}\n\nexport interface PresentPaywallIfNeededOptions extends PresentPaywallOptions {\n /**\n * The identifier of the entitlement that is required.\n * The paywall will only be presented if the user doesn't have this entitlement.\n */\n requiredEntitlementIdentifier: string;\n}\n\n// Using the enum from purchases-typescript-internal-esm instead of defining our own\nexport { PAYWALL_RESULT as PaywallResultEnum };\n\nexport interface PaywallResult {\n /**\n * The result of the paywall presentation.\n */\n result: PAYWALL_RESULT;\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { registerPlugin } from '@capacitor/core';
|
|
2
|
+
const RevenueCatUI = registerPlugin('RevenueCatUI', {
|
|
3
|
+
web: () => import('./web').then((m) => new m.RevenueCatUIWeb()),
|
|
4
|
+
});
|
|
5
|
+
export * from './definitions';
|
|
6
|
+
export { RevenueCatUI };
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,YAAY,GAAG,cAAc,CAAqB,cAAc,EAAE;IACtE,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;CAChE,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,CAAC","sourcesContent":["import { registerPlugin } from '@capacitor/core';\n\nimport type { RevenueCatUIPlugin } from './definitions';\n\nconst RevenueCatUI = registerPlugin<RevenueCatUIPlugin>('RevenueCatUI', {\n web: () => import('./web').then((m) => new m.RevenueCatUIWeb()),\n});\n\nexport * from './definitions';\nexport { RevenueCatUI };\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
import type { PluginListenerHandle } from '@capacitor/core';
|
|
3
|
+
import type { PaywallResult, PresentPaywallIfNeededOptions, PresentPaywallOptions, RevenueCatUIPlugin } from './definitions';
|
|
4
|
+
export declare class RevenueCatUIWeb extends WebPlugin implements RevenueCatUIPlugin {
|
|
5
|
+
private shouldMockWebResults;
|
|
6
|
+
private webNotSupportedErrorMessage;
|
|
7
|
+
constructor();
|
|
8
|
+
setMockWebResults(options: {
|
|
9
|
+
shouldMockWebResults: boolean;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
presentPaywall(options?: PresentPaywallOptions): Promise<PaywallResult>;
|
|
12
|
+
presentPaywallIfNeeded(options: PresentPaywallIfNeededOptions): Promise<PaywallResult>;
|
|
13
|
+
presentCustomerCenter(): Promise<void>;
|
|
14
|
+
addListener(eventName: string, listener: (...args: any[]) => void): Promise<PluginListenerHandle>;
|
|
15
|
+
removeAllListeners(): Promise<void>;
|
|
16
|
+
private mockNonReturningFunctionIfEnabled;
|
|
17
|
+
private mockReturningFunctionIfEnabled;
|
|
18
|
+
}
|
package/dist/esm/web.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
import { PAYWALL_RESULT } from '@revenuecat/purchases-typescript-internal-esm';
|
|
3
|
+
export class RevenueCatUIWeb extends WebPlugin {
|
|
4
|
+
constructor() {
|
|
5
|
+
super();
|
|
6
|
+
this.shouldMockWebResults = false;
|
|
7
|
+
this.webNotSupportedErrorMessage = 'RevenueCatUI is not supported on web platforms.';
|
|
8
|
+
}
|
|
9
|
+
async setMockWebResults(options) {
|
|
10
|
+
this.shouldMockWebResults = options.shouldMockWebResults;
|
|
11
|
+
return Promise.resolve();
|
|
12
|
+
}
|
|
13
|
+
async presentPaywall(options) {
|
|
14
|
+
return this.mockReturningFunctionIfEnabled('presentPaywall', {
|
|
15
|
+
result: PAYWALL_RESULT.NOT_PRESENTED,
|
|
16
|
+
}, options);
|
|
17
|
+
}
|
|
18
|
+
async presentPaywallIfNeeded(options) {
|
|
19
|
+
return this.mockReturningFunctionIfEnabled('presentPaywallIfNeeded', {
|
|
20
|
+
result: PAYWALL_RESULT.NOT_PRESENTED,
|
|
21
|
+
}, options);
|
|
22
|
+
}
|
|
23
|
+
async presentCustomerCenter() {
|
|
24
|
+
return this.mockNonReturningFunctionIfEnabled('presentCustomerCenter');
|
|
25
|
+
}
|
|
26
|
+
addListener(eventName, listener) {
|
|
27
|
+
if (eventName !== 'paywallDisplayed' && eventName !== 'paywallDismissed') {
|
|
28
|
+
console.warn(`Unsupported event: ${eventName}`);
|
|
29
|
+
}
|
|
30
|
+
return super.addListener(eventName, listener);
|
|
31
|
+
}
|
|
32
|
+
removeAllListeners() {
|
|
33
|
+
return super.removeAllListeners();
|
|
34
|
+
}
|
|
35
|
+
mockNonReturningFunctionIfEnabled(functionName) {
|
|
36
|
+
if (!this.shouldMockWebResults) {
|
|
37
|
+
return Promise.reject(this.webNotSupportedErrorMessage);
|
|
38
|
+
}
|
|
39
|
+
console.log(`${functionName} called on web with mocking enabled. No-op`);
|
|
40
|
+
return Promise.resolve();
|
|
41
|
+
}
|
|
42
|
+
mockReturningFunctionIfEnabled(functionName, returnValue, options) {
|
|
43
|
+
if (!this.shouldMockWebResults) {
|
|
44
|
+
return Promise.reject(this.webNotSupportedErrorMessage);
|
|
45
|
+
}
|
|
46
|
+
console.log(`${functionName} called on web with mocking enabled. Returning mocked value`, options);
|
|
47
|
+
return Promise.resolve(returnValue);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAS/E,MAAM,OAAO,eAAgB,SAAQ,SAAS;IAI5C;QACE,KAAK,EAAE,CAAC;QAJF,yBAAoB,GAAG,KAAK,CAAC;QAC7B,gCAA2B,GAAG,iDAAiD,CAAC;IAIxF,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,OAA0C;QAChE,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC;QACzD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAA+B;QAClD,OAAO,IAAI,CAAC,8BAA8B,CACxC,gBAAgB,EAChB;YACE,MAAM,EAAE,cAAc,CAAC,aAAa;SACrC,EACD,OAAO,CACR,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,OAAsC;QACjE,OAAO,IAAI,CAAC,8BAA8B,CACxC,wBAAwB,EACxB;YACE,MAAM,EAAE,cAAc,CAAC,aAAa;SACrC,EACD,OAAO,CACR,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,qBAAqB;QACzB,OAAO,IAAI,CAAC,iCAAiC,CAAC,uBAAuB,CAAC,CAAC;IACzE,CAAC;IAED,WAAW,CAAC,SAAiB,EAAE,QAAkC;QAC/D,IAAI,SAAS,KAAK,kBAAkB,IAAI,SAAS,KAAK,kBAAkB,EAAE;YACxE,OAAO,CAAC,IAAI,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAC;SACjD;QACD,OAAO,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAChD,CAAC;IAED,kBAAkB;QAChB,OAAO,KAAK,CAAC,kBAAkB,EAAE,CAAC;IACpC,CAAC;IAEO,iCAAiC,CAAC,YAAoB;QAC5D,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE;YAC9B,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;SACzD;QACD,OAAO,CAAC,GAAG,CAAC,GAAG,YAAY,4CAA4C,CAAC,CAAC;QACzE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAEO,8BAA8B,CAAI,YAAoB,EAAE,WAAc,EAAE,OAAa;QAC3F,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE;YAC9B,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;SACzD;QACD,OAAO,CAAC,GAAG,CAAC,GAAG,YAAY,6DAA6D,EAAE,OAAO,CAAC,CAAC;QACnG,OAAO,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\nimport type { PluginListenerHandle } from '@capacitor/core';\nimport { PAYWALL_RESULT } from '@revenuecat/purchases-typescript-internal-esm';\n\nimport type {\n PaywallResult,\n PresentPaywallIfNeededOptions,\n PresentPaywallOptions,\n RevenueCatUIPlugin,\n} from './definitions';\n\nexport class RevenueCatUIWeb extends WebPlugin implements RevenueCatUIPlugin {\n private shouldMockWebResults = false;\n private webNotSupportedErrorMessage = 'RevenueCatUI is not supported on web platforms.';\n\n constructor() {\n super();\n }\n\n async setMockWebResults(options: { shouldMockWebResults: boolean }): Promise<void> {\n this.shouldMockWebResults = options.shouldMockWebResults;\n return Promise.resolve();\n }\n\n async presentPaywall(options?: PresentPaywallOptions): Promise<PaywallResult> {\n return this.mockReturningFunctionIfEnabled(\n 'presentPaywall',\n {\n result: PAYWALL_RESULT.NOT_PRESENTED,\n },\n options,\n );\n }\n\n async presentPaywallIfNeeded(options: PresentPaywallIfNeededOptions): Promise<PaywallResult> {\n return this.mockReturningFunctionIfEnabled(\n 'presentPaywallIfNeeded',\n {\n result: PAYWALL_RESULT.NOT_PRESENTED,\n },\n options,\n );\n }\n\n async presentCustomerCenter(): Promise<void> {\n return this.mockNonReturningFunctionIfEnabled('presentCustomerCenter');\n }\n\n addListener(eventName: string, listener: (...args: any[]) => void): Promise<PluginListenerHandle> {\n if (eventName !== 'paywallDisplayed' && eventName !== 'paywallDismissed') {\n console.warn(`Unsupported event: ${eventName}`);\n }\n return super.addListener(eventName, listener);\n }\n\n removeAllListeners(): Promise<void> {\n return super.removeAllListeners();\n }\n\n private mockNonReturningFunctionIfEnabled(functionName: string): Promise<void> {\n if (!this.shouldMockWebResults) {\n return Promise.reject(this.webNotSupportedErrorMessage);\n }\n console.log(`${functionName} called on web with mocking enabled. No-op`);\n return Promise.resolve();\n }\n\n private mockReturningFunctionIfEnabled<T>(functionName: string, returnValue: T, options?: any): Promise<T> {\n if (!this.shouldMockWebResults) {\n return Promise.reject(this.webNotSupportedErrorMessage);\n }\n console.log(`${functionName} called on web with mocking enabled. Returning mocked value`, options);\n return Promise.resolve(returnValue);\n }\n}\n"]}
|