Skip to content
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
8 changes: 6 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ version: 2.1

orbs:
macos: circleci/macos@2.4.1
node: circleci/node@7.1.0
rn: react-native-community/react-native@7.4.0

jobs:
unit-test:
docker:
- image: cimg/node:18.20
- image: cimg/node:22.12

steps:
- checkout
Expand Down Expand Up @@ -68,7 +69,7 @@ jobs:

build-sample-app-ios:
macos:
xcode: 15.2.0
xcode: 16.2.0
resource_class: m2pro.medium

steps:
Expand All @@ -82,6 +83,9 @@ jobs:
name: Set Xcode Path
command: sudo xcode-select -s /Applications/Xcode.app

- node/install:
node-version: '22.12.0'

- run:
name: Install Node.js and Yarn Dependencies
command: yarn install
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@master
with:
node-version: 18.18.0
node-version: 20.19.4
- name: install dependencies
run: yarn install
- name: Authenticate with Registry
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18.18.0
20.19.4
5 changes: 3 additions & 2 deletions apps/AEPSampleAppNewArchEnabled/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,16 @@
"expo-build-properties",
{
"ios": {
"newArchEnabled": true,
"newArchEnabled": true,
"useFrameworks": "static"
},
"android": {
"newArchEnabled": true
}
}
],
"expo-font"
"expo-font",
"expo-web-browser"
],
"experiments": {
"typedRoutes": true
Expand Down
3 changes: 3 additions & 0 deletions apps/AEPSampleAppNewArchEnabled/app/MessagingView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ const setMessagingDelegate = () => {
msg.handleJavascriptMessage('myInappCallback', (content: string) => {
console.log('Received webview content in onShow:', content);
});
msg.evaluateJavascript("(function() {console.log('my test'); return 'some result';})();", (result: string) => {
console.log('Result:', result);
});
},
shouldShowMessage: () => true,
shouldSaveMessage: () => true,
Expand Down
54 changes: 25 additions & 29 deletions apps/AEPSampleAppNewArchEnabled/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,43 +27,39 @@
"@adobe/react-native-aepplaces": "^7.0.0",
"@adobe/react-native-aeptarget": "^7.0.0",
"@adobe/react-native-aepuserprofile": "^7.0.0",
"@expo/vector-icons": "^14.0.2",
"@react-navigation/bottom-tabs": "7.3.12",
"@react-navigation/core": "7.9.1",
"@react-navigation/drawer": "7.3.11",
"@react-navigation/native": "7.1.8",
"@react-navigation/routers": "7.3.7",
"@react-navigation/stack": "7.3.1",
"expo": "~52.0.46",
"expo-build-properties": "~0.13.2",
"expo-constants": "~17.0.8",
"expo-font": "~13.0.4",
"expo-linking": "~7.0.5",
"expo-router": "~4.0.21",
"expo-splash-screen": "~0.29.24",
"expo-status-bar": "~2.0.1",
"expo-system-ui": "~4.0.9",
"expo-web-browser": "~14.0.2",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-native": "0.76.9",
"react-native-gesture-handler": "~2.20.2",
"react-native-reanimated": "~3.16.1",
"react-native-safe-area-context": "4.12.0",
"react-native-screens": "~4.8.0",
"react-native-web": "~0.19.10",
"react-native-webview": "13.12.5",
"@expo/vector-icons": "^15.0.3",
"@react-navigation/drawer": "^7.7.10",
"expo": "^54.0.0",
"expo-build-properties": "~1.0.10",
"expo-constants": "~18.0.12",
"expo-font": "~14.0.10",
"expo-linking": "~8.0.10",
"expo-router": "~6.0.20",
"expo-splash-screen": "~31.0.12",
"expo-status-bar": "~3.0.9",
"expo-system-ui": "~6.0.9",
"expo-web-browser": "~15.0.10",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-native": "0.81.5",
"react-native-gesture-handler": "~2.28.0",
"react-native-reanimated": "~4.1.1",
"react-native-safe-area-context": "~5.6.0",
"react-native-screens": "~4.16.0",
"react-native-web": "^0.21.0",
"react-native-webview": "13.15.0",
"react-native-worklets": "0.5.1",
"recyclerlistview": "^4.2.1"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@types/jest": "^29.5.12",
"@types/react": "~18.3.12",
"@types/react": "~19.1.10",
"@types/react-test-renderer": "^18.0.7",
"jest": "^29.2.1",
"jest-expo": "~52.0.6",
"jest-expo": "~54.0.16",
"react-test-renderer": "18.2.0",
"typescript": "~5.3.3"
"typescript": "~5.9.2"
},
"expo": {
"install": {
Expand Down
2 changes: 1 addition & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
presets: ['module:@react-native/babel-preset'],
};
14 changes: 10 additions & 4 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
module.exports = {
maxConcurrency: 10,
preset: './apps/AEPSampleAppNewArchEnabled/node_modules/react-native/jest-preset.js',
testEnvironment: 'node',
transform: {
'^.+\\.(js)$': '<rootDir>/node_modules/babel-jest',
'\\.(ts|tsx)$': 'ts-jest'
'^.+\\.(js|jsx)$': 'babel-jest',
'^.+\\.(ts|tsx)$': 'ts-jest'
},
transformIgnorePatterns: [
'node_modules/(?!(react-native|@react-native|@react-navigation)/)',
],
setupFiles: ['./tests/jest/setup.ts'],
testMatch: ['**/packages/**/__tests__/*.ts'],
modulePaths: ['node_modules', './apps/AEPSampleAppNewArchEnabled/node_modules'],
testPathIgnorePatterns: ['./packages/template'],
moduleDirectories: ['node_modules', './apps/AEPSampleAppNewArchEnabled/node_modules'],
moduleFileExtensions: ['ts', 'tsx', 'js'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
moduleNameMapper: {
'^react-native$': '<rootDir>/apps/AEPSampleAppNewArchEnabled/node_modules/react-native'
},
};
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,24 @@
"sampleappnewarchenabled:android:run": "cd apps/AEPSampleAppNewArchEnabled && npx expo run:android"
},
"devDependencies": {
"@babel/core": "^7.17.5",
"@babel/generator": "^7.17.3",
"@babel/preset-env": "7.16.11",
"@babel/preset-typescript": "^7.16.7",
"@types/jest": "^27.5.2",
"@babel/core": "^7.25.0",
"@babel/generator": "^7.25.0",
"@babel/preset-env": "^7.25.0",
"@babel/preset-flow": "^7.25.0",
"@babel/preset-typescript": "^7.25.0",
"@react-native/babel-preset": "^0.81.0",
"@types/jest": "^29.5.12",
"@types/react": "^18.0.5",
"@types/react-native": "^0.66.16",
"babel-jest": "^29.7.0",
"babel-plugin-module-resolver": "^4.1.0",
"babel-preset-react-native": "5.0.2",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"lerna": "^8.2.2",
"metro-react-native-babel-preset": "^0.70.1",
"ts-jest": "^29.1.1",
"tslib": "^2.3.1",
"@types/node": "^22.9.0",
"typescript": "^4.5.5"
"typescript": "^5.0.0"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
11 changes: 11 additions & 0 deletions packages/messaging/__tests__/MessagingTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ describe('Messaging', () => {
expect(spy).toHaveBeenCalledWith(id, handlerName);
});

it('evaluateJavascript is called', async () => {
const spy = jest.spyOn(NativeModules.AEPMessaging, 'evaluateJavascript');
let id = 'id';
let autoTrack = true;
let message = new Message({id, autoTrack});
let javascriptString = 'javascriptString';
let callback = jest.fn();
await message.evaluateJavascript(javascriptString, callback);
expect(spy).toHaveBeenCalledWith(id, javascriptString);
});

it('should call updatePropositionsForSurfaces', async () => {
const spy = jest.spyOn(NativeModules.AEPMessaging, 'updatePropositionsForSurfaces');
await Messaging.updatePropositionsForSurfaces([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
class RCTAEPMessagingConstants {
static final String MESSAGE_ID_KEY = "messageId";
static final String HANDLER_NAME_KEY = "handlerName";
static final String JAVASCRIPT_STRING_KEY = "javascriptString";
static final String CONTENT_KEY = "content";
static final String RESULT_KEY = "result";
static final String ON_JAVASCRIPT_MESSAGE_EVENT = "onJavascriptMessage";
static final String ON_JAVASCRIPT_RESULT_EVENT = "onJavascriptResult";
}
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,25 @@ public void handleJavascriptMessage(final String messageId, final String handler
});
}

@ReactMethod
public void evaluateJavascript(final String messageId, final String javascriptString) {
Presentable<?> presentable = presentableCache.get(messageId);
if (presentable == null || !(presentable.getPresentation() instanceof InAppMessage)) {
Log.w(TAG, "evaluateJavascript: No presentable found for messageId: " + messageId);
return;
}

Presentable<InAppMessage> inAppMessagePresentable = (Presentable<InAppMessage>) presentable;
InAppMessageEventHandler eventHandler = inAppMessagePresentable.getPresentation().getEventHandler();
eventHandler.evaluateJavascript(javascriptString, result -> {
Map<String, String> params = new HashMap<>();
params.put(RCTAEPMessagingConstants.MESSAGE_ID_KEY, messageId);
params.put(RCTAEPMessagingConstants.JAVASCRIPT_STRING_KEY, javascriptString);
params.put(RCTAEPMessagingConstants.RESULT_KEY, result);
emitEvent(RCTAEPMessagingConstants.ON_JAVASCRIPT_RESULT_EVENT, params);
});
}

// Messaging Delegate functions
@Override
public void onShow(final Presentable<?> presentable) {
Expand Down Expand Up @@ -335,11 +354,12 @@ public void onContentLoaded(final Presentable<?> presentable, PresentationConten

// Messaging Delegate Callback
@ReactMethod(isBlockingSynchronousMethod = true)
public void setMessageSettings(final boolean shouldShowMessage,
public boolean setMessageSettings(final boolean shouldShowMessage,
final boolean shouldSaveMessage) {
this.shouldShowMessage = shouldShowMessage;
this.shouldSaveMessage = shouldSaveMessage;
latch.countDown();
return true;
}

/**
Expand Down
4 changes: 4 additions & 0 deletions packages/messaging/ios/src/RCTAEPMessaging.mm
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ @interface RCT_EXTERN_MODULE (RCTAEPMessaging, RCTEventEmitter)
: (NSString *)messageId handlerName
: (NSString *)handlerName)

RCT_EXTERN_METHOD(evaluateJavascript
: (NSString *)messageId javascriptString
: (NSString *)javascriptString)

RCT_EXTERN_METHOD(trackPropositionItem
: (NSString *)uuid interaction
: (NSString * _Nullable)interaction eventType
Expand Down
31 changes: 31 additions & 0 deletions packages/messaging/ios/src/RCTAEPMessaging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,37 @@ public class RCTAEPMessaging: RCTEventEmitter, MessagingDelegate {
}
}

@objc
func evaluateJavascript(
_ messageId: String,
javascriptString: String
) {
guard let message = jsHandlerMessageCache[messageId] else {
print("[RCTAEPMessaging] evaluateJavascript: No message found in cache for messageId: \(messageId)")
return
}

guard let messageWebView = message.view as? WKWebView else {
print("[RCTAEPMessaging] evaluateJavascript: Could not get WKWebView from message")
return
}

messageWebView.evaluateJavaScript(javascriptString) { [weak self] result, error in
if let error = error {
print("[RCTAEPMessaging] evaluateJavascript error: \(error)")
}

self?.emitNativeEvent(
name: Constants.ON_JAVASCRIPT_RESULT_EVENT,
body: [
Constants.MESSAGE_ID_KEY: messageId,
Constants.JAVASCRIPT_STRING_KEY: javascriptString,
Constants.RESULT_KEY: result ?? NSNull()
]
)
}
}

/// MARK: - Unified PropositionItem Tracking Methods

/**
Expand Down
5 changes: 4 additions & 1 deletion packages/messaging/ios/src/RCTAEPMessagingConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ class Constants {
static let SHOULD_SHOW_MESSAGE_EVENT = "shouldShowMessage"
static let URL_LOADED_EVENT = "urlLoaded"
static let ON_JAVASCRIPT_MESSAGE_EVENT = "onJavascriptMessage"
static let ON_JAVASCRIPT_RESULT_EVENT = "onJavascriptResult"
static let SUPPORTED_EVENTS = [
ON_DISMISS_EVENT, ON_SHOW_EVENT, SHOULD_SHOW_MESSAGE_EVENT, URL_LOADED_EVENT, ON_JAVASCRIPT_MESSAGE_EVENT
ON_DISMISS_EVENT, ON_SHOW_EVENT, SHOULD_SHOW_MESSAGE_EVENT, URL_LOADED_EVENT, ON_JAVASCRIPT_MESSAGE_EVENT, ON_JAVASCRIPT_RESULT_EVENT
]
static let MESSAGE_ID_KEY = "messageId"
static let HANDLER_NAME_KEY = "handlerName"
static let JAVASCRIPT_STRING_KEY = "javascriptString"
static let CONTENT_KEY = "content"
static let RESULT_KEY = "result"
}
2 changes: 1 addition & 1 deletion packages/messaging/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/react-native-aepmessaging",
"version": "7.2.1",
"version": "7.3.0",
"description": "Adobe Experience Platform support for React Native apps.",
"homepage": "https://developer.adobe.com/client-sdks/documentation/",
"license": "Apache-2.0",
Expand Down
1 change: 1 addition & 0 deletions packages/messaging/src/Messaging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ class Messaging {
eventEmitter.addListener('onDismiss', (message: Message) => {
const messageInstance = new Message(message);
messageInstance._clearJavascriptMessageHandlers();
messageInstance._clearJavascriptResultHandlers();
messagingDelegate?.onDismiss?.(messageInstance);
});

Expand Down
Loading