react-native-userleap 2.21.0 → 3.0.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.
|
@@ -13,8 +13,6 @@ import com.facebook.react.bridge.ReactMethod;
|
|
|
13
13
|
import com.facebook.react.bridge.ReadableArray;
|
|
14
14
|
import com.facebook.react.bridge.ReadableMap;
|
|
15
15
|
import com.facebook.react.bridge.WritableMap;
|
|
16
|
-
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
17
|
-
|
|
18
16
|
import com.userleap.EventListener;
|
|
19
17
|
import com.userleap.EventName;
|
|
20
18
|
import com.userleap.EventPayload;
|
|
@@ -26,13 +24,11 @@ import com.userleap.UserLeap;
|
|
|
26
24
|
import org.json.JSONException;
|
|
27
25
|
import org.json.JSONObject;
|
|
28
26
|
|
|
29
|
-
import java.util.EnumSet;
|
|
30
27
|
import java.util.HashMap;
|
|
31
28
|
import java.util.Iterator;
|
|
32
29
|
import java.util.List;
|
|
33
30
|
import java.util.Map;
|
|
34
31
|
import java.util.Objects;
|
|
35
|
-
import java.util.Set;
|
|
36
32
|
import java.util.stream.Collectors;
|
|
37
33
|
|
|
38
34
|
import javax.annotation.Nullable;
|
|
@@ -44,34 +40,6 @@ public class UserLeapModule extends ReactContextBaseJavaModule {
|
|
|
44
40
|
|
|
45
41
|
private static final String TAG = "UserLeapModule";
|
|
46
42
|
|
|
47
|
-
/**
|
|
48
|
-
* Lifecycle events we forward to React Native via DeviceEventEmitter.
|
|
49
|
-
* Excluded:
|
|
50
|
-
* - LOGGING_EVENT: handled separately via logcat
|
|
51
|
-
* - REPLAY_CAPTURE: internal Web SDK plumbing, not meaningful to RN consumers
|
|
52
|
-
* - REPLAY_EVENTS_UPLOADED_COMPLETED: deprecated alias for REPLAY_EVENTS_UPLOAD_COMPLETED
|
|
53
|
-
*/
|
|
54
|
-
private static final Set<EventName> FORWARDED_EVENTS = EnumSet.of(
|
|
55
|
-
EventName.SDK_READY,
|
|
56
|
-
EventName.VISITOR_ID_UPDATED,
|
|
57
|
-
EventName.SURVEY_HEIGHT,
|
|
58
|
-
EventName.SURVEY_STATE_RETURNED,
|
|
59
|
-
EventName.SURVEY_WILL_PRESENT,
|
|
60
|
-
EventName.SURVEY_PRESENTED,
|
|
61
|
-
EventName.SURVEY_APPEARED,
|
|
62
|
-
EventName.QUESTION_ANSWERED,
|
|
63
|
-
EventName.SURVEY_CLOSE_REQUESTED,
|
|
64
|
-
EventName.SURVEY_WILL_CLOSE,
|
|
65
|
-
EventName.SURVEY_CLOSED,
|
|
66
|
-
EventName.SURVEY_COMPLETED,
|
|
67
|
-
EventName.REPLAY_CAPTURE_STARTED,
|
|
68
|
-
EventName.REPLAY_CAPTURE_STOPPED,
|
|
69
|
-
EventName.REPLAY_CAPTURE_COMPLETED,
|
|
70
|
-
EventName.REPLAY_RENDERING_COMPLETED,
|
|
71
|
-
EventName.REPLAY_UPLOAD_COMPLETED,
|
|
72
|
-
EventName.REPLAY_EVENTS_UPLOAD_COMPLETED
|
|
73
|
-
);
|
|
74
|
-
|
|
75
43
|
private final ReactApplicationContext reactContext;
|
|
76
44
|
|
|
77
45
|
public UserLeapModule(ReactApplicationContext reactContext) {
|
|
@@ -84,48 +52,6 @@ public class UserLeapModule extends ReactContextBaseJavaModule {
|
|
|
84
52
|
return "UserLeapBindings";
|
|
85
53
|
}
|
|
86
54
|
|
|
87
|
-
// ---------------------------------------------------------------------------
|
|
88
|
-
// Required stubs for RN's NativeEventEmitter on the JS side.
|
|
89
|
-
// ---------------------------------------------------------------------------
|
|
90
|
-
|
|
91
|
-
@ReactMethod
|
|
92
|
-
public void addListener(String eventName) {
|
|
93
|
-
// No-op: listeners are registered once in configure() for the SDK lifetime.
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
@ReactMethod
|
|
97
|
-
public void removeListeners(int count) {
|
|
98
|
-
// No-op: listeners are registered once in configure() for the SDK lifetime.
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// ---------------------------------------------------------------------------
|
|
102
|
-
// Lifecycle event registration
|
|
103
|
-
// ---------------------------------------------------------------------------
|
|
104
|
-
|
|
105
|
-
private void registerForAllLifecycleEvents() {
|
|
106
|
-
for (EventName eventName : FORWARDED_EVENTS) {
|
|
107
|
-
UserLeap.INSTANCE.addEventListener(eventName, new EventListener() {
|
|
108
|
-
@Override
|
|
109
|
-
public void onEvent(SprigEvent event) {
|
|
110
|
-
sendSprigEvent(event);
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
private void sendSprigEvent(SprigEvent event) {
|
|
117
|
-
if (!reactContext.hasActiveCatalystInstance()) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
WritableMap params = jsonObjectToWritableMap(event.getData());
|
|
122
|
-
String eventName = toCamelCase(event.getName().name());
|
|
123
|
-
|
|
124
|
-
reactContext
|
|
125
|
-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
126
|
-
.emit(eventName, params);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
55
|
// ---------------------------------------------------------------------------
|
|
130
56
|
// Bridge helpers
|
|
131
57
|
// ---------------------------------------------------------------------------
|
|
@@ -280,8 +206,6 @@ public class UserLeapModule extends ReactContextBaseJavaModule {
|
|
|
280
206
|
}
|
|
281
207
|
});
|
|
282
208
|
|
|
283
|
-
registerForAllLifecycleEvents();
|
|
284
|
-
|
|
285
209
|
UserLeap.INSTANCE.configure(
|
|
286
210
|
reactContext,
|
|
287
211
|
environment,
|
package/index.d.ts
CHANGED
|
@@ -5,31 +5,6 @@ declare namespace UserLeap {
|
|
|
5
5
|
NO_SURVEY: string;
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
const LifecycleEvent: {
|
|
9
|
-
sdkReady: number;
|
|
10
|
-
visitorIdUpdated: number;
|
|
11
|
-
surveyHeight: number;
|
|
12
|
-
surveyWillPresent: number;
|
|
13
|
-
surveyPresented: number;
|
|
14
|
-
surveyAppeared: number;
|
|
15
|
-
surveyCloseRequested: number;
|
|
16
|
-
surveyWillClose: number;
|
|
17
|
-
surveyClosed: number;
|
|
18
|
-
replayCapture: number;
|
|
19
|
-
replayCaptureStarted: number;
|
|
20
|
-
replayCaptureStopped: number;
|
|
21
|
-
replayCaptureCompleted: number;
|
|
22
|
-
replayRenderingCompleted: number;
|
|
23
|
-
replayUploadCompleted: number;
|
|
24
|
-
replayEventsUploadCompleted: number;
|
|
25
|
-
loggingEvent: number;
|
|
26
|
-
surveyCompleted: number;
|
|
27
|
-
surveyStateReturned: number;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// Usage: UserLeap.EventEmitter.addListener('surveyPresented', callback)
|
|
31
|
-
const EventEmitter: any;
|
|
32
|
-
|
|
33
8
|
function visitorIdentifier(): number;
|
|
34
9
|
function visitorIdentifierString(): string;
|
|
35
10
|
function sdkVersion(): string;
|
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Platform, NativeModules
|
|
1
|
+
import { Platform, NativeModules } from "react-native";
|
|
2
2
|
|
|
3
3
|
import { version } from "./package.json";
|
|
4
4
|
|
|
@@ -8,29 +8,6 @@ const SurveyState = {
|
|
|
8
8
|
NO_SURVEY: "NO_SURVEY",
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
const LifecycleEvent = {
|
|
12
|
-
sdkReady: 0,
|
|
13
|
-
visitorIdUpdated: 1,
|
|
14
|
-
surveyHeight: 2,
|
|
15
|
-
surveyWillPresent: 3,
|
|
16
|
-
surveyPresented: 4,
|
|
17
|
-
surveyAppeared: 5,
|
|
18
|
-
surveyCloseRequested: 6,
|
|
19
|
-
surveyWillClose: 7,
|
|
20
|
-
surveyClosed: 8,
|
|
21
|
-
replayCapture: 9,
|
|
22
|
-
replayCaptureStarted: 10,
|
|
23
|
-
replayCaptureStopped: 11,
|
|
24
|
-
replayCaptureCompleted: 12,
|
|
25
|
-
replayRenderingCompleted: 13,
|
|
26
|
-
replayUploadCompleted: 14,
|
|
27
|
-
replayEventsUploadCompleted: 15,
|
|
28
|
-
loggingEvent: 16,
|
|
29
|
-
surveyCompleted: 17,
|
|
30
|
-
surveyStateReturned: 18
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const UserLeapEventEmitter = new NativeEventEmitter(NativeModules.UserLeapBindings);
|
|
34
11
|
|
|
35
12
|
const stringifyAttributes = (attributes) => {
|
|
36
13
|
if (!(attributes instanceof Object && attributes.constructor === Object))
|
|
@@ -45,7 +22,7 @@ const isValidPlatform = () => {
|
|
|
45
22
|
//Platform.Version is a number for android and string for ios
|
|
46
23
|
return (
|
|
47
24
|
(Platform.OS === "android" && String(Platform.Version) >= "21") ||
|
|
48
|
-
(Platform.OS === "ios" && String(Platform.Version) >= "
|
|
25
|
+
(Platform.OS === "ios" && String(Platform.Version) >= "15.0")
|
|
49
26
|
);
|
|
50
27
|
};
|
|
51
28
|
|
|
@@ -307,8 +284,6 @@ const UserLeap = {
|
|
|
307
284
|
unpauseDisplayingSurveys,
|
|
308
285
|
};
|
|
309
286
|
|
|
310
|
-
UserLeap.LifecycleEvent = LifecycleEvent;
|
|
311
287
|
UserLeap.SurveyState = SurveyState;
|
|
312
|
-
UserLeap.EventEmitter = UserLeapEventEmitter;
|
|
313
288
|
|
|
314
289
|
export default UserLeap;
|
package/ios/UserLeapBindings.h
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#import <React/RCTBridgeModule.h>
|
|
2
|
-
#import <React/RCTEventEmitter.h>
|
|
3
2
|
@import UserLeapKit;
|
|
4
3
|
|
|
5
|
-
@interface UserLeapBindings :
|
|
4
|
+
@interface UserLeapBindings : NSObject <RCTBridgeModule, _SGRNExtractor>
|
|
6
5
|
@property (nonatomic, weak) RCTBridge *bridge;
|
|
7
6
|
@end
|
package/ios/UserLeapBindings.m
CHANGED
|
@@ -45,11 +45,6 @@
|
|
|
45
45
|
return surveyStateBinding;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
/// These are required by RCTEventEmitter.
|
|
49
|
-
- (NSArray<NSString *> *)supportedEvents {
|
|
50
|
-
return [LifecycleEventUtil allNameStrings];
|
|
51
|
-
}
|
|
52
|
-
|
|
53
48
|
RCT_EXPORT_MODULE()
|
|
54
49
|
|
|
55
50
|
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(visitorIdentifier)
|
|
@@ -71,32 +66,6 @@ RCT_EXPORT_METHOD(configure:(NSString *)environmentId configuration:(NSDictionar
|
|
|
71
66
|
{
|
|
72
67
|
[[UserLeap shared] configureWithEnvironment:environmentId configuration:configuration];
|
|
73
68
|
[[UserLeap shared] _passWithRnExtractor:self];
|
|
74
|
-
|
|
75
|
-
/// Register for all the LifeCycle events.
|
|
76
|
-
[self registerForAllLifecycleEvents];
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
- (void)registerForAllLifecycleEvents {
|
|
80
|
-
|
|
81
|
-
for (NSNumber *eventVal in [LifecycleEventUtil all]) {
|
|
82
|
-
[[UserLeap shared] registerEventListenerFor:[eventVal intValue] listener:^(NSDictionary<NSString *,id> * eventData) {
|
|
83
|
-
|
|
84
|
-
NSString *type = eventData[LifecycleEventDataKey.eventType];
|
|
85
|
-
if (!type) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
LifecycleEvent lifecycleEvent = [LifecycleEventUtil fromString:type];
|
|
90
|
-
if (lifecycleEvent != LifecycleEventUnknown) {
|
|
91
|
-
|
|
92
|
-
/// Always make sure the type exists in the supportedEvents; sending an unsupported event will crash the app.
|
|
93
|
-
NSString *lifecycleEventName = [LifecycleEventUtil stringName:lifecycleEvent];
|
|
94
|
-
if ([[self supportedEvents] containsObject: lifecycleEventName]) {
|
|
95
|
-
[self sendEventWithName:lifecycleEventName body:eventData];
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}];
|
|
99
|
-
}
|
|
100
69
|
}
|
|
101
70
|
|
|
102
71
|
|
|
@@ -245,21 +214,54 @@ RCT_EXPORT_METHOD(trackIdentifyAndPresent:(NSString *)eventName userId:(NSString
|
|
|
245
214
|
}
|
|
246
215
|
|
|
247
216
|
- (_SGRNTextProperties *)textPropertiesFromView:(UIView * _Nonnull)passedView {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
217
|
+
|
|
218
|
+
// Legacy for pre new arch.
|
|
219
|
+
if ([passedView isKindOfClass:[RCTTextView class]]) {
|
|
220
|
+
RCTUIManager* uiManager = [self.bridge moduleForClass:[RCTUIManager class]];
|
|
221
|
+
RCTTextView *textView = (RCTTextView *)passedView;
|
|
222
|
+
__block _SGRNTextProperties *textProperties = [[_SGRNTextProperties alloc] init];
|
|
223
|
+
dispatch_sync(RCTGetUIManagerQueue(), ^{
|
|
224
|
+
RCTShadowView *shadowView = [uiManager shadowViewForReactTag:textView.reactTag];
|
|
225
|
+
if ([shadowView isKindOfClass:[RCTTextShadowView class]]) {
|
|
226
|
+
RCTTextShadowView *textShadowView = (RCTTextShadowView *)shadowView;
|
|
227
|
+
NSString *text = [self extractText: textShadowView.reactSubviews];
|
|
228
|
+
if (text.length == 0) return;
|
|
229
|
+
textProperties.text = text;
|
|
230
|
+
textProperties.color = textShadowView.textAttributes.foregroundColor;
|
|
231
|
+
textProperties.alignment = textShadowView.textAttributes.alignment;
|
|
232
|
+
textProperties.font = textShadowView.textAttributes.effectiveFont;
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
if (textProperties.text.length == 0) return nil;
|
|
236
|
+
return textProperties;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Text under new arch.
|
|
240
|
+
Class ParagraphComponentView = NSClassFromString(@"RCTParagraphComponentView");
|
|
241
|
+
if (ParagraphComponentView && [passedView isKindOfClass:ParagraphComponentView]) {
|
|
242
|
+
NSString *text = [self extractTextFromParagraphComponentView:passedView];
|
|
243
|
+
if (text.length == 0) return nil;
|
|
244
|
+
_SGRNTextProperties *textProperties = [[_SGRNTextProperties alloc] init];
|
|
245
|
+
textProperties.text = text;
|
|
246
|
+
if ([passedView respondsToSelector:@selector(attributedText)]) {
|
|
247
|
+
NSAttributedString *attrText = [passedView performSelector:@selector(attributedText)];
|
|
248
|
+
if (attrText.length > 0) {
|
|
249
|
+
NSDictionary *attrs = [attrText attributesAtIndex:0 effectiveRange:nil];
|
|
250
|
+
if (!textProperties.color && attrs[NSForegroundColorAttributeName]) {
|
|
251
|
+
textProperties.color = attrs[NSForegroundColorAttributeName];
|
|
252
|
+
}
|
|
253
|
+
if (!textProperties.font && attrs[NSFontAttributeName]) {
|
|
254
|
+
textProperties.font = attrs[NSFontAttributeName];
|
|
255
|
+
}
|
|
256
|
+
NSParagraphStyle *style = attrs[NSParagraphStyleAttributeName];
|
|
257
|
+
if (style) {
|
|
258
|
+
textProperties.alignment = style.alignment;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
260
261
|
}
|
|
261
|
-
|
|
262
|
-
|
|
262
|
+
return textProperties;
|
|
263
|
+
}
|
|
264
|
+
return nil;
|
|
263
265
|
}
|
|
264
266
|
|
|
265
267
|
RCT_EXPORT_METHOD(dismissActiveSurvey)
|
|
@@ -302,4 +304,22 @@ RCT_EXPORT_METHOD(unpauseDisplayingSurveys)
|
|
|
302
304
|
}
|
|
303
305
|
return text;
|
|
304
306
|
}
|
|
307
|
+
|
|
308
|
+
- (NSString *)extractTextFromParagraphComponentView:(UIView *)view {
|
|
309
|
+
if ([view respondsToSelector:@selector(attributedText)]) {
|
|
310
|
+
NSAttributedString *attrText = [view performSelector:@selector(attributedText)];
|
|
311
|
+
return attrText.string;
|
|
312
|
+
}
|
|
313
|
+
if ([view respondsToSelector:@selector(text)]) {
|
|
314
|
+
NSString *text = [view performSelector:@selector(text)];
|
|
315
|
+
return text;
|
|
316
|
+
}
|
|
317
|
+
NSMutableString *result = [NSMutableString string];
|
|
318
|
+
for (UIView *subview in view.subviews) {
|
|
319
|
+
NSString *subText = [self extractTextFromParagraphComponentView:subview];
|
|
320
|
+
if (subText) [result appendString:subText];
|
|
321
|
+
}
|
|
322
|
+
return result;
|
|
323
|
+
}
|
|
324
|
+
|
|
305
325
|
@end
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-userleap",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "React Native module for UserLeap",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -17,11 +17,6 @@
|
|
|
17
17
|
"scripts": {
|
|
18
18
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
19
19
|
},
|
|
20
|
-
"repository": {
|
|
21
|
-
"type": "git",
|
|
22
|
-
"url": "git+https://github.com/UserLeap/react-native-userleap.git",
|
|
23
|
-
"baseUrl": "https://github.com/UserLeap/react-native-userleap"
|
|
24
|
-
},
|
|
25
20
|
"keywords": [
|
|
26
21
|
"userleap",
|
|
27
22
|
"react-native",
|
|
@@ -38,9 +33,12 @@
|
|
|
38
33
|
"babel-jest": "29.7.0",
|
|
39
34
|
"eslint": "7.32.0",
|
|
40
35
|
"jest": "29.7.0",
|
|
41
|
-
"
|
|
42
|
-
"react": "
|
|
43
|
-
"react-native": "0.
|
|
36
|
+
"@react-native/babel-preset": "^0.81.0",
|
|
37
|
+
"react": "19.1.0",
|
|
38
|
+
"react-native": "0.81.0",
|
|
44
39
|
"react-test-renderer": "18.2.0"
|
|
40
|
+
},
|
|
41
|
+
"overrides": {
|
|
42
|
+
"js-yaml": "3.14.2"
|
|
45
43
|
}
|
|
46
44
|
}
|