rampkit-expo-dev 0.0.18 → 0.0.22
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/android/build.gradle +87 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/expo/modules/rampkit/RampKitModule.kt +445 -0
- package/build/DeviceInfoCollector.d.ts +21 -0
- package/build/DeviceInfoCollector.js +200 -0
- package/build/EventManager.d.ts +155 -0
- package/build/EventManager.js +419 -0
- package/build/RampKit.d.ts +93 -9
- package/build/RampKit.js +224 -21
- package/build/RampKitNative.d.ts +151 -0
- package/build/RampKitNative.js +255 -0
- package/build/RampkitOverlay.d.ts +8 -0
- package/build/RampkitOverlay.js +72 -106
- package/build/constants.d.ts +18 -0
- package/build/constants.js +29 -0
- package/build/index.d.ts +12 -0
- package/build/index.js +30 -1
- package/build/types.d.ts +178 -0
- package/build/types.js +5 -0
- package/build/userId.d.ts +8 -0
- package/build/userId.js +28 -72
- package/expo-module.config.json +10 -0
- package/ios/RampKit.podspec +22 -0
- package/ios/RampKitModule.swift +407 -0
- package/package.json +9 -7
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* RampKit Native Module Bridge
|
|
4
|
+
* TypeScript interface to the native iOS/Android module
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.Notifications = exports.StoreReview = exports.Haptics = void 0;
|
|
8
|
+
exports.getDeviceInfo = getDeviceInfo;
|
|
9
|
+
exports.getUserId = getUserId;
|
|
10
|
+
exports.getStoredValue = getStoredValue;
|
|
11
|
+
exports.setStoredValue = setStoredValue;
|
|
12
|
+
exports.getLaunchTrackingData = getLaunchTrackingData;
|
|
13
|
+
const expo_modules_core_1 = require("expo-modules-core");
|
|
14
|
+
const react_native_1 = require("react-native");
|
|
15
|
+
// Get the native module
|
|
16
|
+
let RampKitNativeModule;
|
|
17
|
+
try {
|
|
18
|
+
RampKitNativeModule = (0, expo_modules_core_1.requireNativeModule)("RampKit");
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
console.warn("[RampKit] Native module not available. Using JavaScript fallback.");
|
|
22
|
+
RampKitNativeModule = createFallbackModule();
|
|
23
|
+
}
|
|
24
|
+
// Fallback module for when native module is not available
|
|
25
|
+
function createFallbackModule() {
|
|
26
|
+
return {
|
|
27
|
+
async getDeviceInfo() {
|
|
28
|
+
return getFallbackDeviceInfo();
|
|
29
|
+
},
|
|
30
|
+
async getUserId() {
|
|
31
|
+
return generateFallbackUserId();
|
|
32
|
+
},
|
|
33
|
+
async getStoredValue(_key) {
|
|
34
|
+
return null;
|
|
35
|
+
},
|
|
36
|
+
async setStoredValue(_key, _value) { },
|
|
37
|
+
async getLaunchTrackingData() {
|
|
38
|
+
return {
|
|
39
|
+
installDate: new Date().toISOString(),
|
|
40
|
+
isFirstLaunch: true,
|
|
41
|
+
launchCount: 1,
|
|
42
|
+
lastLaunchAt: null,
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
async impactAsync(_style) { },
|
|
46
|
+
async notificationAsync(_type) { },
|
|
47
|
+
async selectionAsync() { },
|
|
48
|
+
async requestReview() {
|
|
49
|
+
return false;
|
|
50
|
+
},
|
|
51
|
+
async isReviewAvailable() {
|
|
52
|
+
return false;
|
|
53
|
+
},
|
|
54
|
+
async getStoreUrl() {
|
|
55
|
+
return null;
|
|
56
|
+
},
|
|
57
|
+
async requestNotificationPermissions(_options) {
|
|
58
|
+
return { granted: false, status: "denied", canAskAgain: false };
|
|
59
|
+
},
|
|
60
|
+
async getNotificationPermissions() {
|
|
61
|
+
return { granted: false, status: "denied", canAskAgain: false };
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function generateFallbackUserId() {
|
|
66
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
67
|
+
const r = (Math.random() * 16) | 0;
|
|
68
|
+
const v = c === "x" ? r : (r & 0x3) | 0x8;
|
|
69
|
+
return v.toString(16);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function getFallbackDeviceInfo() {
|
|
73
|
+
const now = new Date().toISOString();
|
|
74
|
+
return {
|
|
75
|
+
appUserId: generateFallbackUserId(),
|
|
76
|
+
vendorId: null,
|
|
77
|
+
appSessionId: generateFallbackUserId(),
|
|
78
|
+
installDate: now,
|
|
79
|
+
isFirstLaunch: true,
|
|
80
|
+
launchCount: 1,
|
|
81
|
+
lastLaunchAt: null,
|
|
82
|
+
bundleId: null,
|
|
83
|
+
appName: null,
|
|
84
|
+
appVersion: null,
|
|
85
|
+
buildNumber: null,
|
|
86
|
+
platform: react_native_1.Platform.OS === "ios" ? "iOS" : "Android",
|
|
87
|
+
platformVersion: String(react_native_1.Platform.Version),
|
|
88
|
+
deviceModel: "unknown",
|
|
89
|
+
deviceName: "unknown",
|
|
90
|
+
isSimulator: false,
|
|
91
|
+
deviceLanguageCode: null,
|
|
92
|
+
deviceLocale: "en_US",
|
|
93
|
+
regionCode: null,
|
|
94
|
+
preferredLanguage: null,
|
|
95
|
+
preferredLanguages: [],
|
|
96
|
+
deviceCurrencyCode: null,
|
|
97
|
+
deviceCurrencySymbol: null,
|
|
98
|
+
timezoneIdentifier: "UTC",
|
|
99
|
+
timezoneOffsetSeconds: 0,
|
|
100
|
+
interfaceStyle: "unspecified",
|
|
101
|
+
screenWidth: 0,
|
|
102
|
+
screenHeight: 0,
|
|
103
|
+
screenScale: 1,
|
|
104
|
+
isLowPowerMode: false,
|
|
105
|
+
totalMemoryBytes: 0,
|
|
106
|
+
collectedAt: now,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// Export the native module
|
|
110
|
+
exports.default = RampKitNativeModule;
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// Convenience exports for Device Info
|
|
113
|
+
// ============================================================================
|
|
114
|
+
async function getDeviceInfo() {
|
|
115
|
+
return RampKitNativeModule.getDeviceInfo();
|
|
116
|
+
}
|
|
117
|
+
async function getUserId() {
|
|
118
|
+
return RampKitNativeModule.getUserId();
|
|
119
|
+
}
|
|
120
|
+
async function getStoredValue(key) {
|
|
121
|
+
return RampKitNativeModule.getStoredValue(key);
|
|
122
|
+
}
|
|
123
|
+
async function setStoredValue(key, value) {
|
|
124
|
+
return RampKitNativeModule.setStoredValue(key, value);
|
|
125
|
+
}
|
|
126
|
+
async function getLaunchTrackingData() {
|
|
127
|
+
return RampKitNativeModule.getLaunchTrackingData();
|
|
128
|
+
}
|
|
129
|
+
// ============================================================================
|
|
130
|
+
// Haptics API (replaces expo-haptics)
|
|
131
|
+
// ============================================================================
|
|
132
|
+
exports.Haptics = {
|
|
133
|
+
/**
|
|
134
|
+
* Trigger an impact haptic feedback
|
|
135
|
+
*/
|
|
136
|
+
async impactAsync(style = "medium") {
|
|
137
|
+
try {
|
|
138
|
+
await RampKitNativeModule.impactAsync(style);
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
// Silently fail - haptics are non-critical
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
/**
|
|
145
|
+
* Trigger a notification haptic feedback
|
|
146
|
+
*/
|
|
147
|
+
async notificationAsync(type = "success") {
|
|
148
|
+
try {
|
|
149
|
+
await RampKitNativeModule.notificationAsync(type);
|
|
150
|
+
}
|
|
151
|
+
catch (e) {
|
|
152
|
+
// Silently fail
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
/**
|
|
156
|
+
* Trigger a selection haptic feedback
|
|
157
|
+
*/
|
|
158
|
+
async selectionAsync() {
|
|
159
|
+
try {
|
|
160
|
+
await RampKitNativeModule.selectionAsync();
|
|
161
|
+
}
|
|
162
|
+
catch (e) {
|
|
163
|
+
// Silently fail
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
// ============================================================================
|
|
168
|
+
// Store Review API (replaces expo-store-review)
|
|
169
|
+
// ============================================================================
|
|
170
|
+
exports.StoreReview = {
|
|
171
|
+
/**
|
|
172
|
+
* Request an in-app review
|
|
173
|
+
*/
|
|
174
|
+
async requestReview() {
|
|
175
|
+
try {
|
|
176
|
+
await RampKitNativeModule.requestReview();
|
|
177
|
+
}
|
|
178
|
+
catch (e) {
|
|
179
|
+
console.warn("[RampKit] Failed to request review:", e);
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
/**
|
|
183
|
+
* Check if in-app review is available
|
|
184
|
+
*/
|
|
185
|
+
async isAvailableAsync() {
|
|
186
|
+
try {
|
|
187
|
+
return await RampKitNativeModule.isReviewAvailable();
|
|
188
|
+
}
|
|
189
|
+
catch (e) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
/**
|
|
194
|
+
* Check if the review action is available
|
|
195
|
+
*/
|
|
196
|
+
async hasAction() {
|
|
197
|
+
return true;
|
|
198
|
+
},
|
|
199
|
+
/**
|
|
200
|
+
* Get the store URL for the app
|
|
201
|
+
*/
|
|
202
|
+
storeUrl() {
|
|
203
|
+
// This is synchronous in the original API, so we can't await here
|
|
204
|
+
// Return null and let callers handle it
|
|
205
|
+
return null;
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
// ============================================================================
|
|
209
|
+
// Notifications API (replaces expo-notifications)
|
|
210
|
+
// ============================================================================
|
|
211
|
+
exports.Notifications = {
|
|
212
|
+
/**
|
|
213
|
+
* Request notification permissions
|
|
214
|
+
*/
|
|
215
|
+
async requestPermissionsAsync(options) {
|
|
216
|
+
try {
|
|
217
|
+
return await RampKitNativeModule.requestNotificationPermissions(options);
|
|
218
|
+
}
|
|
219
|
+
catch (e) {
|
|
220
|
+
return { granted: false, status: "denied", canAskAgain: false };
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
/**
|
|
224
|
+
* Get current notification permissions
|
|
225
|
+
*/
|
|
226
|
+
async getPermissionsAsync() {
|
|
227
|
+
try {
|
|
228
|
+
return await RampKitNativeModule.getNotificationPermissions();
|
|
229
|
+
}
|
|
230
|
+
catch (e) {
|
|
231
|
+
return { granted: false, status: "denied", canAskAgain: false };
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
/**
|
|
235
|
+
* Set notification handler (no-op in native implementation)
|
|
236
|
+
* The app should handle this separately if needed
|
|
237
|
+
*/
|
|
238
|
+
setNotificationHandler(_handler) {
|
|
239
|
+
// No-op - notification handling is done by the app
|
|
240
|
+
},
|
|
241
|
+
/**
|
|
242
|
+
* Android notification channel creation is handled in requestPermissionsAsync
|
|
243
|
+
*/
|
|
244
|
+
async setNotificationChannelAsync(_channelId, _options) {
|
|
245
|
+
// No-op - handled in requestPermissionsAsync
|
|
246
|
+
},
|
|
247
|
+
// Android importance constants for compatibility
|
|
248
|
+
AndroidImportance: {
|
|
249
|
+
MAX: 5,
|
|
250
|
+
HIGH: 4,
|
|
251
|
+
DEFAULT: 3,
|
|
252
|
+
LOW: 2,
|
|
253
|
+
MIN: 1,
|
|
254
|
+
},
|
|
255
|
+
};
|
|
@@ -14,6 +14,10 @@ export declare function showRampkitOverlay(opts: {
|
|
|
14
14
|
onClose?: () => void;
|
|
15
15
|
onOnboardingFinished?: (payload?: any) => void;
|
|
16
16
|
onShowPaywall?: (payload?: any) => void;
|
|
17
|
+
onScreenChange?: (screenIndex: number, screenId: string) => void;
|
|
18
|
+
onOnboardingAbandoned?: (reason: string, lastScreenIndex: number, lastScreenId: string) => void;
|
|
19
|
+
onNotificationPermissionRequested?: () => void;
|
|
20
|
+
onNotificationPermissionResult?: (granted: boolean) => void;
|
|
17
21
|
}): void;
|
|
18
22
|
export declare function hideRampkitOverlay(): void;
|
|
19
23
|
export declare function closeRampkitOverlay(): void;
|
|
@@ -33,5 +37,9 @@ declare function Overlay(props: {
|
|
|
33
37
|
onOnboardingFinished?: (payload?: any) => void;
|
|
34
38
|
onShowPaywall?: (payload?: any) => void;
|
|
35
39
|
onRegisterClose?: (handler: (() => void) | null) => void;
|
|
40
|
+
onScreenChange?: (screenIndex: number, screenId: string) => void;
|
|
41
|
+
onOnboardingAbandoned?: (reason: string, lastScreenIndex: number, lastScreenId: string) => void;
|
|
42
|
+
onNotificationPermissionRequested?: () => void;
|
|
43
|
+
onNotificationPermissionResult?: (granted: boolean) => void;
|
|
36
44
|
}): any;
|
|
37
45
|
export default Overlay;
|
package/build/RampkitOverlay.js
CHANGED
|
@@ -47,9 +47,7 @@ const react_native_1 = require("react-native");
|
|
|
47
47
|
const react_native_root_siblings_1 = __importDefault(require("react-native-root-siblings"));
|
|
48
48
|
const react_native_pager_view_1 = __importDefault(require("react-native-pager-view"));
|
|
49
49
|
const react_native_webview_1 = require("react-native-webview");
|
|
50
|
-
const
|
|
51
|
-
const StoreReview = __importStar(require("expo-store-review"));
|
|
52
|
-
const Notifications = __importStar(require("expo-notifications"));
|
|
50
|
+
const RampKitNative_1 = require("./RampKitNative");
|
|
53
51
|
// Reuse your injected script from App
|
|
54
52
|
exports.injectedHardening = `
|
|
55
53
|
(function(){
|
|
@@ -131,7 +129,7 @@ function performRampkitHaptic(event) {
|
|
|
131
129
|
if (!event || event.action !== "haptic") {
|
|
132
130
|
// Backwards compatible default
|
|
133
131
|
try {
|
|
134
|
-
Haptics.impactAsync(
|
|
132
|
+
RampKitNative_1.Haptics.impactAsync("medium").catch(() => { });
|
|
135
133
|
}
|
|
136
134
|
catch (_) { }
|
|
137
135
|
return;
|
|
@@ -140,46 +138,36 @@ function performRampkitHaptic(event) {
|
|
|
140
138
|
try {
|
|
141
139
|
if (hapticType === "impact") {
|
|
142
140
|
const styleMap = {
|
|
143
|
-
Light:
|
|
144
|
-
Medium:
|
|
145
|
-
Heavy:
|
|
146
|
-
Rigid:
|
|
147
|
-
Soft:
|
|
141
|
+
Light: "light",
|
|
142
|
+
Medium: "medium",
|
|
143
|
+
Heavy: "heavy",
|
|
144
|
+
Rigid: "rigid",
|
|
145
|
+
Soft: "soft",
|
|
148
146
|
};
|
|
149
|
-
const impactStyle = event.impactStyle
|
|
150
|
-
|
|
151
|
-
? event.impactStyle
|
|
152
|
-
: "Medium";
|
|
153
|
-
const style = (impactStyle && styleMap[impactStyle]) ||
|
|
154
|
-
Haptics.ImpactFeedbackStyle.Medium;
|
|
155
|
-
Haptics.impactAsync(style).catch(() => { });
|
|
147
|
+
const impactStyle = styleMap[event.impactStyle] || "medium";
|
|
148
|
+
RampKitNative_1.Haptics.impactAsync(impactStyle).catch(() => { });
|
|
156
149
|
return;
|
|
157
150
|
}
|
|
158
151
|
if (hapticType === "notification") {
|
|
159
152
|
const notificationMap = {
|
|
160
|
-
Success:
|
|
161
|
-
Warning:
|
|
162
|
-
Error:
|
|
153
|
+
Success: "success",
|
|
154
|
+
Warning: "warning",
|
|
155
|
+
Error: "error",
|
|
163
156
|
};
|
|
164
|
-
const notificationType = event.notificationType
|
|
165
|
-
|
|
166
|
-
? event.notificationType
|
|
167
|
-
: "Success";
|
|
168
|
-
const style = (notificationType && notificationMap[notificationType]) ||
|
|
169
|
-
Haptics.NotificationFeedbackType.Success;
|
|
170
|
-
Haptics.notificationAsync(style).catch(() => { });
|
|
157
|
+
const notificationType = notificationMap[event.notificationType] || "success";
|
|
158
|
+
RampKitNative_1.Haptics.notificationAsync(notificationType).catch(() => { });
|
|
171
159
|
return;
|
|
172
160
|
}
|
|
173
161
|
if (hapticType === "selection") {
|
|
174
|
-
Haptics.selectionAsync().catch(() => { });
|
|
162
|
+
RampKitNative_1.Haptics.selectionAsync().catch(() => { });
|
|
175
163
|
return;
|
|
176
164
|
}
|
|
177
165
|
// Fallback for unknown hapticType
|
|
178
|
-
Haptics.impactAsync(
|
|
166
|
+
RampKitNative_1.Haptics.impactAsync("medium").catch(() => { });
|
|
179
167
|
}
|
|
180
168
|
catch (_) {
|
|
181
169
|
try {
|
|
182
|
-
Haptics.impactAsync(
|
|
170
|
+
RampKitNative_1.Haptics.impactAsync("medium").catch(() => { });
|
|
183
171
|
}
|
|
184
172
|
catch (__) { }
|
|
185
173
|
}
|
|
@@ -200,7 +188,7 @@ function showRampkitOverlay(opts) {
|
|
|
200
188
|
(_a = opts.onClose) === null || _a === void 0 ? void 0 : _a.call(opts);
|
|
201
189
|
}, onOnboardingFinished: opts.onOnboardingFinished, onShowPaywall: opts.onShowPaywall, onRegisterClose: (handler) => {
|
|
202
190
|
activeCloseHandler = handler;
|
|
203
|
-
} })));
|
|
191
|
+
}, onScreenChange: opts.onScreenChange, onOnboardingAbandoned: opts.onOnboardingAbandoned, onNotificationPermissionRequested: opts.onNotificationPermissionRequested, onNotificationPermissionResult: opts.onNotificationPermissionResult })));
|
|
204
192
|
// Once shown, we can safely discard the preloader sibling if present
|
|
205
193
|
if (preloadSibling) {
|
|
206
194
|
preloadSibling.destroy();
|
|
@@ -306,9 +294,11 @@ function Overlay(props) {
|
|
|
306
294
|
const [visible, setVisible] = (0, react_1.useState)(false);
|
|
307
295
|
const [isTransitioning, setIsTransitioning] = (0, react_1.useState)(false);
|
|
308
296
|
const [isClosing, setIsClosing] = (0, react_1.useState)(false);
|
|
297
|
+
const [onboardingCompleted, setOnboardingCompleted] = (0, react_1.useState)(false);
|
|
309
298
|
const overlayOpacity = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
|
|
310
299
|
const fadeOpacity = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
|
|
311
300
|
const allLoaded = loadedCount >= props.screens.length;
|
|
301
|
+
const hasTrackedInitialScreen = (0, react_1.useRef)(false);
|
|
312
302
|
// shared vars across all webviews
|
|
313
303
|
const varsRef = (0, react_1.useRef)({});
|
|
314
304
|
// hold refs for injection
|
|
@@ -326,10 +316,15 @@ function Overlay(props) {
|
|
|
326
316
|
}).start();
|
|
327
317
|
}
|
|
328
318
|
}, [visible, isClosing, overlayOpacity]);
|
|
329
|
-
const handleRequestClose = react_1.default.useCallback(() => {
|
|
319
|
+
const handleRequestClose = react_1.default.useCallback((options) => {
|
|
330
320
|
if (isClosing)
|
|
331
321
|
return;
|
|
332
322
|
setIsClosing(true);
|
|
323
|
+
// Track abandonment if not completed
|
|
324
|
+
const isCompleted = (options === null || options === void 0 ? void 0 : options.completed) || onboardingCompleted;
|
|
325
|
+
if (!isCompleted && props.onOnboardingAbandoned && props.screens[index]) {
|
|
326
|
+
props.onOnboardingAbandoned("dismissed", index, props.screens[index].id);
|
|
327
|
+
}
|
|
333
328
|
react_native_1.Animated.sequence([
|
|
334
329
|
react_native_1.Animated.delay(150),
|
|
335
330
|
react_native_1.Animated.timing(overlayOpacity, {
|
|
@@ -341,7 +336,7 @@ function Overlay(props) {
|
|
|
341
336
|
]).start(() => {
|
|
342
337
|
props.onRequestClose();
|
|
343
338
|
});
|
|
344
|
-
}, [isClosing, overlayOpacity, props.onRequestClose]);
|
|
339
|
+
}, [isClosing, overlayOpacity, props.onRequestClose, onboardingCompleted, index, props.screens, props.onOnboardingAbandoned]);
|
|
345
340
|
react_1.default.useEffect(() => {
|
|
346
341
|
var _a;
|
|
347
342
|
(_a = props.onRegisterClose) === null || _a === void 0 ? void 0 : _a.call(props, handleRequestClose);
|
|
@@ -476,73 +471,49 @@ function Overlay(props) {
|
|
|
476
471
|
if (__DEV__)
|
|
477
472
|
console.log("[Rampkit] onPageSelected", pos);
|
|
478
473
|
sendVarsToWebView(pos);
|
|
474
|
+
// Track screen change event
|
|
475
|
+
if (props.onScreenChange && props.screens[pos]) {
|
|
476
|
+
props.onScreenChange(pos, props.screens[pos].id);
|
|
477
|
+
}
|
|
479
478
|
};
|
|
480
479
|
const handleAdvance = (i, animation = "fade") => {
|
|
481
480
|
const last = props.screens.length - 1;
|
|
482
481
|
if (i < last) {
|
|
483
482
|
navigateToIndex(i + 1, animation);
|
|
484
|
-
Haptics.impactAsync(
|
|
483
|
+
RampKitNative_1.Haptics.impactAsync("light").catch(() => { });
|
|
485
484
|
}
|
|
486
485
|
else {
|
|
487
|
-
// finish
|
|
488
|
-
|
|
489
|
-
|
|
486
|
+
// finish - mark as completed before closing
|
|
487
|
+
setOnboardingCompleted(true);
|
|
488
|
+
RampKitNative_1.Haptics.notificationAsync("success").catch(() => { });
|
|
489
|
+
handleRequestClose({ completed: true });
|
|
490
490
|
}
|
|
491
491
|
};
|
|
492
492
|
async function handleNotificationPermissionRequest(payload) {
|
|
493
|
+
var _a, _b;
|
|
494
|
+
// Track that notification permission was requested
|
|
495
|
+
try {
|
|
496
|
+
(_a = props.onNotificationPermissionRequested) === null || _a === void 0 ? void 0 : _a.call(props);
|
|
497
|
+
}
|
|
498
|
+
catch (_) { }
|
|
493
499
|
const iosDefaults = { allowAlert: true, allowBadge: true, allowSound: true };
|
|
494
500
|
const androidDefaults = {
|
|
495
501
|
channelId: "default",
|
|
496
502
|
name: "Default Channel",
|
|
497
503
|
importance: "MAX",
|
|
498
504
|
};
|
|
499
|
-
const behaviorDefaults = { shouldShowBanner: true, shouldPlaySound: false };
|
|
500
505
|
const iosReq = { ...((payload === null || payload === void 0 ? void 0 : payload.ios) || iosDefaults) };
|
|
501
506
|
const androidCfg = { ...((payload === null || payload === void 0 ? void 0 : payload.android) || androidDefaults) };
|
|
502
|
-
const behavior = { ...((payload === null || payload === void 0 ? void 0 : payload.behavior) || behaviorDefaults) };
|
|
503
|
-
try {
|
|
504
|
-
// Set foreground behavior
|
|
505
|
-
Notifications.setNotificationHandler({
|
|
506
|
-
handleNotification: async () => ({
|
|
507
|
-
shouldShowAlert: !!behavior.shouldShowBanner,
|
|
508
|
-
shouldPlaySound: !!behavior.shouldPlaySound,
|
|
509
|
-
shouldSetBadge: false,
|
|
510
|
-
}),
|
|
511
|
-
});
|
|
512
|
-
}
|
|
513
|
-
catch (_) { }
|
|
514
|
-
try {
|
|
515
|
-
// Minimal Android 13+ permission + channel config
|
|
516
|
-
if (react_native_1.Platform.OS === "android") {
|
|
517
|
-
const importanceMap = {
|
|
518
|
-
MAX: Notifications.AndroidImportance.MAX,
|
|
519
|
-
HIGH: Notifications.AndroidImportance.HIGH,
|
|
520
|
-
DEFAULT: Notifications.AndroidImportance.DEFAULT,
|
|
521
|
-
LOW: Notifications.AndroidImportance.LOW,
|
|
522
|
-
MIN: Notifications.AndroidImportance.MIN,
|
|
523
|
-
};
|
|
524
|
-
const mappedImportance = importanceMap[String(androidCfg.importance || "MAX").toUpperCase()] ||
|
|
525
|
-
Notifications.AndroidImportance.MAX;
|
|
526
|
-
if (androidCfg.channelId && androidCfg.name) {
|
|
527
|
-
try {
|
|
528
|
-
await Notifications.setNotificationChannelAsync(androidCfg.channelId, {
|
|
529
|
-
name: androidCfg.name,
|
|
530
|
-
importance: mappedImportance,
|
|
531
|
-
});
|
|
532
|
-
}
|
|
533
|
-
catch (_) { }
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
catch (_) { }
|
|
538
507
|
let result = null;
|
|
539
508
|
try {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
509
|
+
result = await RampKitNative_1.Notifications.requestPermissionsAsync({
|
|
510
|
+
ios: iosReq,
|
|
511
|
+
android: {
|
|
512
|
+
channelId: androidCfg.channelId,
|
|
513
|
+
name: androidCfg.name,
|
|
514
|
+
importance: (androidCfg.importance || "MAX"),
|
|
515
|
+
},
|
|
516
|
+
});
|
|
546
517
|
}
|
|
547
518
|
catch (e) {
|
|
548
519
|
result = {
|
|
@@ -556,6 +527,11 @@ function Overlay(props) {
|
|
|
556
527
|
console.log("[Rampkit] Notification permission status:", result);
|
|
557
528
|
}
|
|
558
529
|
catch (_) { }
|
|
530
|
+
// Track notification permission result
|
|
531
|
+
try {
|
|
532
|
+
(_b = props.onNotificationPermissionResult) === null || _b === void 0 ? void 0 : _b.call(props, !!(result === null || result === void 0 ? void 0 : result.granted));
|
|
533
|
+
}
|
|
534
|
+
catch (_) { }
|
|
559
535
|
// Save to shared vars and broadcast to all pages
|
|
560
536
|
try {
|
|
561
537
|
varsRef.current = {
|
|
@@ -564,9 +540,7 @@ function Overlay(props) {
|
|
|
564
540
|
granted: !!(result === null || result === void 0 ? void 0 : result.granted),
|
|
565
541
|
status: (result === null || result === void 0 ? void 0 : result.status) || "undetermined",
|
|
566
542
|
canAskAgain: !!(result === null || result === void 0 ? void 0 : result.canAskAgain),
|
|
567
|
-
expires: (result === null || result === void 0 ? void 0 : result.expires) || "never",
|
|
568
543
|
ios: result === null || result === void 0 ? void 0 : result.ios,
|
|
569
|
-
android: result === null || result === void 0 ? void 0 : result.android,
|
|
570
544
|
},
|
|
571
545
|
};
|
|
572
546
|
broadcastVars();
|
|
@@ -579,8 +553,14 @@ function Overlay(props) {
|
|
|
579
553
|
visible && { opacity: overlayOpacity },
|
|
580
554
|
], pointerEvents: visible && !isClosing ? "auto" : "none", children: [(0, jsx_runtime_1.jsx)(react_native_pager_view_1.default, { ref: pagerRef, style: react_native_1.StyleSheet.absoluteFill, scrollEnabled: false, initialPage: 0, onPageSelected: onPageSelected, offscreenPageLimit: props.screens.length, overScrollMode: "never", children: docs.map((doc, i) => ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.page, renderToHardwareTextureAndroid: true, children: (0, jsx_runtime_1.jsx)(react_native_webview_1.WebView, { ref: (r) => (webviewsRef.current[i] = r), style: styles.webview, originWhitelist: ["*"], source: { html: doc }, injectedJavaScriptBeforeContentLoaded: exports.injectedHardening, injectedJavaScript: exports.injectedNoSelect, automaticallyAdjustContentInsets: false, contentInsetAdjustmentBehavior: "never", bounces: false, scrollEnabled: false, overScrollMode: "never", scalesPageToFit: false, showsHorizontalScrollIndicator: false, dataDetectorTypes: "none", allowsLinkPreview: false, allowsInlineMediaPlayback: true, mediaPlaybackRequiresUserAction: false, cacheEnabled: true, javaScriptEnabled: true, domStorageEnabled: true, hideKeyboardAccessoryView: true, onLoadEnd: () => {
|
|
581
555
|
setLoadedCount((c) => c + 1);
|
|
582
|
-
if (i === 0)
|
|
556
|
+
if (i === 0) {
|
|
583
557
|
setFirstPageLoaded(true);
|
|
558
|
+
// Track initial screen view
|
|
559
|
+
if (!hasTrackedInitialScreen.current && props.onScreenChange && props.screens[0]) {
|
|
560
|
+
hasTrackedInitialScreen.current = true;
|
|
561
|
+
props.onScreenChange(0, props.screens[0].id);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
584
564
|
// Initialize this page with current vars
|
|
585
565
|
if (__DEV__)
|
|
586
566
|
console.log("[Rampkit] onLoadEnd init send vars", i);
|
|
@@ -637,17 +617,9 @@ function Overlay(props) {
|
|
|
637
617
|
(data === null || data === void 0 ? void 0 : data.type) === "rampkit:review") {
|
|
638
618
|
(async () => {
|
|
639
619
|
try {
|
|
640
|
-
const available = await StoreReview.isAvailableAsync();
|
|
641
|
-
if (available
|
|
642
|
-
await StoreReview.requestReview();
|
|
643
|
-
return;
|
|
644
|
-
}
|
|
645
|
-
const url = StoreReview.storeUrl();
|
|
646
|
-
if (url) {
|
|
647
|
-
const writeUrl = react_native_1.Platform.OS === "ios"
|
|
648
|
-
? `${url}${url.includes("?") ? "&" : "?"}action=write-review`
|
|
649
|
-
: url;
|
|
650
|
-
await react_native_1.Linking.openURL(writeUrl);
|
|
620
|
+
const available = await RampKitNative_1.StoreReview.isAvailableAsync();
|
|
621
|
+
if (available) {
|
|
622
|
+
await RampKitNative_1.StoreReview.requestReview();
|
|
651
623
|
}
|
|
652
624
|
}
|
|
653
625
|
catch (_) { }
|
|
@@ -665,11 +637,12 @@ function Overlay(props) {
|
|
|
665
637
|
}
|
|
666
638
|
// 5) Onboarding finished event from page
|
|
667
639
|
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:onboarding-finished") {
|
|
640
|
+
setOnboardingCompleted(true);
|
|
668
641
|
try {
|
|
669
642
|
(_a = props.onOnboardingFinished) === null || _a === void 0 ? void 0 : _a.call(props, data === null || data === void 0 ? void 0 : data.payload);
|
|
670
643
|
}
|
|
671
644
|
catch (_) { }
|
|
672
|
-
handleRequestClose();
|
|
645
|
+
handleRequestClose({ completed: true });
|
|
673
646
|
return;
|
|
674
647
|
}
|
|
675
648
|
// 6) Request to show paywall
|
|
@@ -738,17 +711,9 @@ function Overlay(props) {
|
|
|
738
711
|
if (raw === "rampkit:request-review" || raw === "rampkit:review") {
|
|
739
712
|
(async () => {
|
|
740
713
|
try {
|
|
741
|
-
const available = await StoreReview.isAvailableAsync();
|
|
742
|
-
if (available
|
|
743
|
-
await StoreReview.requestReview();
|
|
744
|
-
return;
|
|
745
|
-
}
|
|
746
|
-
const url = StoreReview.storeUrl();
|
|
747
|
-
if (url) {
|
|
748
|
-
const writeUrl = react_native_1.Platform.OS === "ios"
|
|
749
|
-
? `${url}${url.includes("?") ? "&" : "?"}action=write-review`
|
|
750
|
-
: url;
|
|
751
|
-
await react_native_1.Linking.openURL(writeUrl);
|
|
714
|
+
const available = await RampKitNative_1.StoreReview.isAvailableAsync();
|
|
715
|
+
if (available) {
|
|
716
|
+
await RampKitNative_1.StoreReview.requestReview();
|
|
752
717
|
}
|
|
753
718
|
}
|
|
754
719
|
catch (_) { }
|
|
@@ -760,11 +725,12 @@ function Overlay(props) {
|
|
|
760
725
|
return;
|
|
761
726
|
}
|
|
762
727
|
if (raw === "rampkit:onboarding-finished") {
|
|
728
|
+
setOnboardingCompleted(true);
|
|
763
729
|
try {
|
|
764
730
|
(_c = props.onOnboardingFinished) === null || _c === void 0 ? void 0 : _c.call(props, undefined);
|
|
765
731
|
}
|
|
766
732
|
catch (_) { }
|
|
767
|
-
handleRequestClose();
|
|
733
|
+
handleRequestClose({ completed: true });
|
|
768
734
|
return;
|
|
769
735
|
}
|
|
770
736
|
if (raw === "rampkit:show-paywall") {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RampKit SDK Constants
|
|
3
|
+
*/
|
|
4
|
+
export declare const SDK_VERSION = "1.0.0";
|
|
5
|
+
export declare const ENDPOINTS: {
|
|
6
|
+
readonly BASE_URL: "https://uustlzuvjmochxkxatfx.supabase.co/functions/v1";
|
|
7
|
+
readonly APP_USERS: "/app-users";
|
|
8
|
+
readonly APP_USER_EVENTS: "/app-user-events";
|
|
9
|
+
};
|
|
10
|
+
export declare const MANIFEST_BASE_URL = "https://dh1psiwzzzkgr.cloudfront.net";
|
|
11
|
+
export declare const STORAGE_KEYS: {
|
|
12
|
+
readonly APP_USER_ID: "rk_user_id";
|
|
13
|
+
readonly INSTALL_DATE: "rk_install_date";
|
|
14
|
+
readonly LAUNCH_COUNT: "rk_launch_count";
|
|
15
|
+
readonly LAST_LAUNCH: "rk_last_launch";
|
|
16
|
+
};
|
|
17
|
+
export declare const CAPABILITIES: readonly ["onboarding", "paywall_event_receiver", "haptic_feedback", "push_notifications"];
|
|
18
|
+
export declare const SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InV1c3RsenV2am1vY2h4a3hhdGZ4Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzU1NjQ0NjYsImV4cCI6MjA1MTE0MDQ2Nn0.5cNrph5LHmssNo39UKpULkC9n4OD5n6gsnTEQV-gwQk";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* RampKit SDK Constants
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SUPABASE_ANON_KEY = exports.CAPABILITIES = exports.STORAGE_KEYS = exports.MANIFEST_BASE_URL = exports.ENDPOINTS = exports.SDK_VERSION = void 0;
|
|
7
|
+
exports.SDK_VERSION = "1.0.0";
|
|
8
|
+
exports.ENDPOINTS = {
|
|
9
|
+
BASE_URL: "https://uustlzuvjmochxkxatfx.supabase.co/functions/v1",
|
|
10
|
+
APP_USERS: "/app-users",
|
|
11
|
+
APP_USER_EVENTS: "/app-user-events",
|
|
12
|
+
};
|
|
13
|
+
exports.MANIFEST_BASE_URL = "https://dh1psiwzzzkgr.cloudfront.net";
|
|
14
|
+
exports.STORAGE_KEYS = {
|
|
15
|
+
// SecureStore (sensitive)
|
|
16
|
+
APP_USER_ID: "rk_user_id",
|
|
17
|
+
// AsyncStorage (persisted)
|
|
18
|
+
INSTALL_DATE: "rk_install_date",
|
|
19
|
+
LAUNCH_COUNT: "rk_launch_count",
|
|
20
|
+
LAST_LAUNCH: "rk_last_launch",
|
|
21
|
+
};
|
|
22
|
+
exports.CAPABILITIES = [
|
|
23
|
+
"onboarding",
|
|
24
|
+
"paywall_event_receiver",
|
|
25
|
+
"haptic_feedback",
|
|
26
|
+
"push_notifications",
|
|
27
|
+
];
|
|
28
|
+
// Supabase anon key for API calls
|
|
29
|
+
exports.SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InV1c3RsenV2am1vY2h4a3hhdGZ4Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzU1NjQ0NjYsImV4cCI6MjA1MTE0MDQ2Nn0.5cNrph5LHmssNo39UKpULkC9n4OD5n6gsnTEQV-gwQk";
|
package/build/index.d.ts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RampKit Expo SDK
|
|
3
|
+
* Main entry point for the SDK
|
|
4
|
+
*/
|
|
1
5
|
import { RampKitCore } from "./RampKit";
|
|
2
6
|
export declare const RampKit: RampKitCore;
|
|
3
7
|
export { getRampKitUserId } from "./userId";
|
|
8
|
+
export { eventManager } from "./EventManager";
|
|
9
|
+
export { collectDeviceInfo, getSessionDurationSeconds, getSessionStartTime, } from "./DeviceInfoCollector";
|
|
10
|
+
export { default as RampKitNative } from "./RampKitNative";
|
|
11
|
+
export type { NativeDeviceInfo, NativeLaunchData } from "./RampKitNative";
|
|
12
|
+
export { Haptics, StoreReview, Notifications } from "./RampKitNative";
|
|
13
|
+
export type { ImpactStyle, NotificationType, NotificationOptions, NotificationPermissionResult } from "./RampKitNative";
|
|
14
|
+
export type { DeviceInfo, RampKitEvent, EventDevice, EventContext, RampKitConfig, RampKitEventName, AppSessionStartedProperties, AppSessionEndedProperties, AppBackgroundedProperties, AppForegroundedProperties, OnboardingStartedProperties, OnboardingScreenViewedProperties, OnboardingQuestionAnsweredProperties, OnboardingCompletedProperties, OnboardingAbandonedProperties, ScreenViewProperties, CtaTapProperties, NotificationsPromptShownProperties, NotificationsResponseProperties, PaywallShownProperties, PaywallPrimaryActionTapProperties, PaywallClosedProperties, PurchaseStartedProperties, PurchaseCompletedProperties, PurchaseFailedProperties, } from "./types";
|
|
15
|
+
export { SDK_VERSION, CAPABILITIES } from "./constants";
|