Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ryanwang/add pages api #67

Merged
merged 9 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions android/src/legacy/java/com/FullStoryModule.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
package com.fullstory.reactnative;

import androidx.annotation.NonNull;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactContext;

import java.util.Map;
import java.util.HashMap;

import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

public class FullStoryModule extends ReactContextBaseJavaModule {

Expand Down Expand Up @@ -86,4 +76,19 @@ public static void log(double level, String message) {
public static void resetIdleTimer() {
FullStoryModuleImpl.resetIdleTimer();
}

@ReactMethod
public static void startPage(String nonce, String pageName, ReadableMap pageProperties) {
FullStoryModuleImpl.startPage(nonce, pageName, pageProperties);
}

@ReactMethod
public static void updatePage(String uuid, ReadableMap pageProperties) {
FullStoryModuleImpl.updatePage(uuid, pageProperties);
}

@ReactMethod
public static void endPage(String uuid) {
FullStoryModuleImpl.endPage(uuid);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.fullstory.reactnative;

import android.util.Log;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReadableMap;
Expand All @@ -8,12 +10,42 @@
import com.fullstory.FSOnReadyListener;
import com.fullstory.FSSessionData;

import java.util.UUID;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import java.lang.reflect.Method;
public class FullStoryModuleImpl {

public static final String NAME = "FullStory";
private static final String TAG = "FullStoryModuleImpl";
public static final boolean reflectionSuccess;
private static final Method PAGE_VIEW;
private static final Method UPDATE_PAGE_PROPERTIES;
private static final Method END_PAGE;

static {
Method pageView;
Method updatePageProperties;
Method endPage;
try {
pageView = FS.class.getMethod("__pageView", UUID.class, String.class, Map.class);
updatePageProperties = FS.class.getMethod("__updatePageProperties", UUID.class, Map.class);
endPage = FS.class.getMethod("__endPage", UUID.class);
} catch (Throwable t) {
pageView = null;
updatePageProperties = null;
endPage = null;
Log.e(TAG, "Unable to access native FullStory pages API. Pages API will not function correctly. " +
"Make sure that your plugin is at least version 1.41; if the issue persists, please contact FullStory Support.");
}

PAGE_VIEW = pageView;
UPDATE_PAGE_PROPERTIES = updatePageProperties;
END_PAGE = endPage;

reflectionSuccess = PAGE_VIEW != null && UPDATE_PAGE_PROPERTIES != null && END_PAGE != null;
}


public static void anonymize() {
FS.anonymize();
Expand Down Expand Up @@ -137,4 +169,45 @@ private static Map toMap(ReadableMap map) {

return map.toHashMap();
}

public static void startPage(String uuid, String pageName, ReadableMap pageProperties) {
if (!reflectionSuccess) {
return;
}

UUID nonce = UUID.fromString(uuid);
try {
PAGE_VIEW.invoke(null, nonce, pageName, toMap(pageProperties));
} catch (Throwable t) {
// this should never happen
Log.e(TAG, "Unexpected error while calling startPage. Please contact FullStory Support.");
}
}

public static void updatePage(String uuid, ReadableMap pageProperties) {
if (!reflectionSuccess) {
return;
}
UUID nonce = UUID.fromString(uuid);

try {
UPDATE_PAGE_PROPERTIES.invoke(null, nonce, toMap(pageProperties));
} catch (Throwable t) {
// this should never happen
Log.e(TAG, "Unexpected error while calling updatePage. Please contact FullStory Support.");
}
}

public static void endPage(String uuid) {
if (!reflectionSuccess) {
return;
}
UUID nonce = UUID.fromString(uuid);
try {
END_PAGE.invoke(null, nonce);
} catch (Throwable t) {
// this should never happen
Log.e(TAG, "Unexpected error while calling endPage. Please contact FullStory Support.");
}
}
}
26 changes: 15 additions & 11 deletions android/src/turbo/java/com/FullStoryModule.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
package com.fullstory.reactnative;

import androidx.annotation.NonNull;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactContext;

import java.util.Map;
import java.util.HashMap;

import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

public class FullStoryModule extends NativeFullStorySpec {

Expand Down Expand Up @@ -87,4 +76,19 @@ public void log(double level, String message) {
public void resetIdleTimer() {
FullStoryModuleImpl.resetIdleTimer();
}

@Override
public void startPage(String nonce, String pageName, ReadableMap pageProperties) {
FullStoryModuleImpl.startPage(nonce, pageName, pageProperties);
}

@Override
public void updatePage(String uuid, ReadableMap pageProperties) {
FullStoryModuleImpl.updatePage(uuid, pageProperties);
}

@Override
public void endPage(String uuid) {
FullStoryModuleImpl.endPage(uuid);
}
}
3 changes: 3 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
};
6 changes: 6 additions & 0 deletions ios/FullStory.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
@interface FullStory : NSObject <RCTBridgeModule, FSDelegate>
@end

@interface FS(FSPrivate)
+ (void) _pageViewWithNonce:(NSUUID *)nonce name:(NSString *)pageName properties:(NSDictionary<NSString *, id> *)properties;
+ (void) _updatePageWithNonce:(NSUUID *)nonce properties:(NSDictionary<NSString *, id> *)properties;
+ (void) _endPageWithNonce:(NSUUID *)nonce;
@end

#ifdef RCT_NEW_ARCH_ENABLED
@interface FullStory () <NativeFullStorySpec>
@end
Expand Down
42 changes: 42 additions & 0 deletions ios/FullStory.mm
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
#import <React/RCTView.h>
#import <React/RCTViewManager.h>
#import <React/RCTComponentData.h>
#import <React/RCTLog.h>

#import "FSReactSwizzle.h"

@implementation FullStory {
RCTPromiseResolveBlock onReadyPromise;
}

NSString *const PagesAPIError = @"Unable to access native FullStory pages API and call %@. Pages API will not function correctly. Make sure that your plugin is at least version 1.41; if the issue persists, please contact FullStory Support.";

RCT_EXPORT_MODULE()

RCT_EXPORT_METHOD(anonymize)
Expand Down Expand Up @@ -128,6 +131,45 @@ - (void) getCurrentSessionURL:(RCTPromiseResolveBlock)resolve reject:(RCTPromise
});
}

RCT_EXPORT_METHOD(startPage:(NSString *)nonce pageName:(NSString *)pageName pageProperties:(NSDictionary *)pageProperties)
{
if (![FS respondsToSelector:@selector(_pageViewWithNonce:name:properties:)]) {
RCTLogError(PagesAPIError, @"startPage");
} else {
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:nonce];

dispatch_async(dispatch_get_main_queue(), ^{
[FS _pageViewWithNonce:uuid name:pageName properties:pageProperties];
});
}
}

RCT_EXPORT_METHOD(endPage:(NSString *)nonce)
{
if (![FS respondsToSelector:@selector(_endPageWithNonce:)]) {
RCTLogError(PagesAPIError, @"endPage");
} else {
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:nonce];

dispatch_async(dispatch_get_main_queue(), ^{
[FS _endPageWithNonce:uuid];
});
}
}

RCT_EXPORT_METHOD(updatePage:(NSString *)nonce pageProperties:(NSDictionary *)pageProperties)
{
if (![FS respondsToSelector:@selector(_updatePageWithNonce:properties:)]) {
RCTLogError(PagesAPIError, @"updatePage");
} else {
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:nonce];

dispatch_async(dispatch_get_main_queue(), ^{
[FS _updatePageWithNonce:uuid properties:pageProperties];
});
}
}

- (void) fullstoryDidStartSession:(NSString *)sessionUrl {
if (!onReadyPromise)
return;
Expand Down
12 changes: 12 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = {
preset: 'react-native',
moduleFileExtensions: ['ts', 'tsx', 'js'],
setupFiles: ['<rootDir>/setupTests.js'],
testRegex: '(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$',
transform: {
'^.+\\.(js)$': 'babel-jest',
'\\.(ts|tsx)$': 'ts-jest',
},
transformIgnorePatterns: ['<rootDir>/node_modules/(?!(@react-native|react-native)/).*/'],
testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/plugin', '<rootDir>/lib'],
};
Loading