diff --git a/.circleci/config.yml b/.circleci/config.yml
index dd5facd39..953c5d786 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -8,36 +8,45 @@ orbs:
jobs:
unit-test:
docker:
- - image: cimg/node:18.20
+ - image: cimg/node:18.20
+ resource_class: large
steps:
- - checkout
+ - checkout
- - restore_cache:
- keys:
+ - restore_cache:
+ keys:
- yarn-cache-{{ checksum "yarn.lock" }}
+ - yarn-cache-
- - run:
- name: Install Node.js and Yarn Dependencies
- command: yarn install
+ - run:
+ name: Enable Corepack
+ command: corepack enable
- - run:
- name: Build the Project
- command: yarn run build
+ - run:
+ name: Install Node.js and Yarn Dependencies
+ command: yarn install --immutable --network-timeout 300000
+ no_output_timeout: 20m
+ environment:
+ NODE_OPTIONS: "--max-old-space-size=4096"
- - run:
- name: Expo Prebuild
- command: cd apps/AEPSampleAppNewArchEnabled && npx expo prebuild
+ - run:
+ name: Build the Project
+ command: yarn run build
- - save_cache:
- key: yarn-cache-{{ checksum "yarn.lock" }}
- paths:
- - ./node_modules
- - ./apps/AEPSampleAppNewArchEnabled/node_modules
+ - run:
+ name: Expo Prebuild
+ command: cd apps/AEPSampleAppNewArchEnabled && npx expo prebuild
- - run:
- name: Unit Tests
- command: yarn test --watchAll=false --runInBand
+ - save_cache:
+ paths:
+ - .yarn/cache
+ - .yarn/unplugged
+ key: yarn-cache-{{ checksum "yarn.lock" }}
+
+ - run:
+ name: Unit Tests
+ command: yarn test --watchAll=false --runInBand
build-sample-app-android:
executor:
@@ -46,86 +55,101 @@ jobs:
resource_class: large
steps:
- - checkout
+ - checkout
+
+ - run:
+ name: Enable Corepack
+ command: corepack enable
- - run:
- name: Install Node.js and Yarn Dependencies
- command: yarn install
+ - run:
+ name: Install Node.js and Yarn Dependencies
+ command: yarn install --network-timeout 300000
+ no_output_timeout: 20m
+ environment:
+ NODE_OPTIONS: "--max-old-space-size=4096"
- - run:
- name: Build the Project
- command: yarn run build
+ - run:
+ name: Build the Project
+ command: yarn run build
- - run:
- name: Expo Prebuild
- command: cd apps/AEPSampleAppNewArchEnabled && npx expo prebuild
+ - run:
+ name: Expo Prebuild
+ command: cd apps/AEPSampleAppNewArchEnabled && npx expo prebuild
- - run:
- name: Building Android Sample App
- command: yarn sampleappnewarchenabled:android:build
- environment:
- _JAVA_OPTIONS: "-Xmx4096M -XX:MaxMetaspaceSize=512m"
+ - run:
+ name: Building Android Sample App
+ command: yarn sampleappnewarchenabled:android:build
+ environment:
+ _JAVA_OPTIONS: "-Xmx4096M -XX:MaxMetaspaceSize=512m"
build-sample-app-ios:
macos:
xcode: 15.2
steps:
- - checkout
-
- - restore_cache:
- keys:
- - ios-yarn-cache-{{ checksum "yarn.lock" }}
-
- - run:
- name: Set Xcode Path
- command: sudo xcode-select -s /Applications/Xcode.app
-
- - run:
- name: Install Node.js and Yarn Dependencies
- command: yarn install
-
- - run:
- name: Build the Project
- command: yarn run build
-
- - run:
- name: Expo Prebuild
- command: cd apps/AEPSampleAppNewArchEnabled && npx expo prebuild
-
- - save_cache:
- key: ios-yarn-cache-{{ checksum "yarn.lock" }}
- paths:
- - ./node_modules
- - ./apps/AEPSampleAppNewArchEnabled/node_modules
-
- - run:
- name: Install Cocoapods
- command: sudo gem install cocoapods
-
- - run:
- name: Install Pods
- command: yarn sampleappnewarchenabled:ios:pod:install
-
- - run:
- name: Building iOS Sample App
- command: |
- cd apps/AEPSampleAppNewArchEnabled/ios
- xcodebuild \
- -workspace AEPSampleAppNewArchEnabled.xcworkspace \
- -scheme AEPSampleAppNewArchEnabled \
- -sdk iphonesimulator \
- -destination "generic/platform=iOS Simulator" \
- clean build
+ - checkout
+
+ - restore_cache:
+ keys:
+ - yarn-cache-{{ checksum "yarn.lock" }}
+ - yarn-cache-
+
+ - run:
+ name: Set Xcode Path
+ command: sudo xcode-select -s /Applications/Xcode.app
+
+ - run:
+ name: Enable Corepack
+ command: corepack enable
+
+ - run:
+ name: Install Node.js and Yarn Dependencies
+ command: yarn install --immutable --network-timeout 300000
+ no_output_timeout: 20m
+ environment:
+ NODE_OPTIONS: "--max-old-space-size=4096"
+
+ - run:
+ name: Build the Project
+ command: yarn run build
+
+ - run:
+ name: Expo Prebuild
+ command: cd apps/AEPSampleAppNewArchEnabled && npx expo prebuild
+
+ - save_cache:
+ paths:
+ - .yarn/cache
+ - .yarn/unplugged
+ key: yarn-cache-{{ checksum "yarn.lock" }}
+
+ - run:
+ name: Install Cocoapods
+ command: sudo gem install cocoapods
+
+ - run:
+ name: Install Pods
+ command: yarn sampleappnewarchenabled:ios:pod:install
+
+ - run:
+ name: Building iOS Sample App
+ command: |
+ cd apps/AEPSampleAppNewArchEnabled/ios
+ xcodebuild \
+ -workspace AEPSampleAppNewArchEnabled.xcworkspace \
+ -scheme AEPSampleAppNewArchEnabled \
+ -sdk iphonesimulator \
+ -destination "generic/platform=iOS Simulator" \
+ clean build
workflows:
version: 2.1
ci-workflow:
jobs:
- - unit-test
- - build-sample-app-ios
- # - build-sample-app-android
- # Disable the Android build job because of the error below:
- # Execution failed for task ':react-native-reanimated:configureCMakeDebug[arm64-v8a]'.
- # > [CXX1210] /root/project/apps/AEPSampleApp/node_modules/react-native-reanimated/android/CMakeLists.txt debug|arm64-v8a : No compatible library found
- # The Android build job will be enabled once the issue is resolved.
+ - unit-test
+ - build-sample-app-ios
+ # - build-sample-app-android
+ # Disable the Android build job because of the error below:
+ # Execution failed for task ':react-native-reanimated:configureCMakeDebug[arm64-v8a]'.
+ # > [CXX1210] /root/project/apps/AEPSampleApp/node_modules/react-native-reanimated/android/CMakeLists.txt debug|arm64-v8a : No compatible library found
+ # The Android build job will be enabled once the issue is resolved.
diff --git a/.cursorignore b/.cursorignore
new file mode 100644
index 000000000..0dda499a5
--- /dev/null
+++ b/.cursorignore
@@ -0,0 +1 @@
+apps/AEPSampleApp
\ No newline at end of file
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000..025dd8c8b
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,8 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..af3ad1281
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,4 @@
+/.yarn/** linguist-vendored
+/.yarn/releases/* binary
+/.yarn/plugins/**/* binary
+/.pnp.* binary linguist-generated
diff --git a/.gitignore b/.gitignore
index 48e6d3b41..77fb31a48 100644
--- a/.gitignore
+++ b/.gitignore
@@ -152,3 +152,6 @@ out/
# ignore ds store
.DS_Store
+
+# temporary allow messaging compiled code
+!packages/messaging/dist/
\ No newline at end of file
diff --git a/.yarnrc.yml b/.yarnrc.yml
index 3186f3f07..de80f2bac 100644
--- a/.yarnrc.yml
+++ b/.yarnrc.yml
@@ -1 +1,2 @@
nodeLinker: node-modules
+nmHoistingLimits: workspaces
diff --git a/apps/AEPSampleApp/package.json b/apps/AEPSampleApp/package.json
index ed441a15f..f6bb17703 100644
--- a/apps/AEPSampleApp/package.json
+++ b/apps/AEPSampleApp/package.json
@@ -2,11 +2,6 @@
"name": "aepsampleapp",
"version": "2.0.0",
"private": true,
- "workspaces": {
- "nohoist": [
- "**/*"
- ]
- },
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
@@ -66,6 +61,7 @@
"node": ">=16"
},
"installConfig": {
- "hoistingLimits": "dependencies"
+ "hoistingLimits": "workspaces",
+ "selfReferences": false
}
}
diff --git a/apps/AEPSampleAppNewArchEnabled/app.json b/apps/AEPSampleAppNewArchEnabled/app.json
index 94ea742e7..fc17cfaee 100644
--- a/apps/AEPSampleAppNewArchEnabled/app.json
+++ b/apps/AEPSampleAppNewArchEnabled/app.json
@@ -14,14 +14,14 @@
},
"ios": {
"supportsTablet": true,
- "bundleIdentifier": "com.AEPSampleAppNewArchEnabled"
+ "bundleIdentifier": "com.adobe.MessagingDemoAppSwiftUI"
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/images/adaptive-icon.png",
"backgroundColor": "#ffffff"
},
- "package": "com.AEPSampleAppNewArchEnabled"
+ "package": "com.adobe.marketing.mobile.messagingsample"
},
"web": {
"bundler": "metro",
@@ -34,11 +34,12 @@
"expo-build-properties",
{
"ios": {
- "newArchEnabled": true,
+ "newArchEnabled": true,
"useFrameworks": "static"
},
"android": {
- "newArchEnabled": true
+ "newArchEnabled": true,
+ "kotlinVersion": "1.9.25"
}
}
],
diff --git a/apps/AEPSampleAppNewArchEnabled/app/AssuranceView.tsx b/apps/AEPSampleAppNewArchEnabled/app/AssuranceView.tsx
index 7015ec8f8..5a72d3795 100644
--- a/apps/AEPSampleAppNewArchEnabled/app/AssuranceView.tsx
+++ b/apps/AEPSampleAppNewArchEnabled/app/AssuranceView.tsx
@@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag
governing permissions and limitations under the License.
*/
-import React, {useState} from 'react';
+import React, { useState } from "react";
import {
Button,
StyleSheet,
@@ -18,30 +18,30 @@ import {
View,
TextInput,
ScrollView,
-} from 'react-native';
-import {Assurance} from '@adobe/react-native-aepassurance';
-import { useRouter } from 'expo-router';
+} from "react-native";
+import { Assurance } from "@adobe/react-native-aepassurance";
+import { useRouter } from "expo-router";
const AssuranceView = () => {
- const [version, setVersion] = useState('');
- const [sessionURL, setsessionURL] = useState('your-assurance-url');
+ const [version, setVersion] = useState("");
+ const [sessionURL, setsessionURL] = useState("your-assurance-url");
const router = useRouter();
- Assurance.extensionVersion().then(version => {
+ Assurance.extensionVersion().then((version) => {
setVersion(version);
});
return (
-
-
+
+
Assurance v{version}
setsessionURL(val)}
+ onChangeText={(val) => setsessionURL(val)}
/>
@@ -55,13 +55,13 @@ const AssuranceView = () => {
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: '#F5FCFF',
+ justifyContent: "center",
+ alignItems: "center",
+ backgroundColor: "#F5FCFF",
},
welcome: {
fontSize: 25,
- textAlign: 'center',
+ textAlign: "center",
margin: 10,
marginTop: 80,
},
diff --git a/apps/AEPSampleAppNewArchEnabled/app/ContentCardsView.tsx b/apps/AEPSampleAppNewArchEnabled/app/ContentCardsView.tsx
new file mode 100644
index 000000000..8a3303a8a
--- /dev/null
+++ b/apps/AEPSampleAppNewArchEnabled/app/ContentCardsView.tsx
@@ -0,0 +1,432 @@
+/*
+Copyright 2025 Adobe. All rights reserved.
+This file is licensed to you under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License. You may obtain a copy
+of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under
+the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
+OF ANY KIND, either express or implied. See the License for the specific language
+governing permissions and limitations under the License.
+*/
+
+import { MobileCore } from "@adobe/react-native-aepcore";
+import {
+ ContentCardView,
+ ContentCardContainer,
+ ThemeProvider,
+ useContentCardUI,
+ Pagination,
+ Messaging,
+ ContentCardContainerProvider,
+} from "@adobe/react-native-aepmessaging";
+import React, { memo, useCallback, useEffect, useState } from "react";
+import {
+ Appearance,
+ ColorSchemeName,
+ FlatList,
+ Modal,
+ Platform,
+ StyleSheet,
+ Text,
+ TextInput,
+ TouchableOpacity,
+ View,
+} from "react-native";
+import { Colors } from "../constants/Colors";
+import { useColorScheme } from "../hooks/useColorScheme";
+import {
+ DemoItem,
+ IMAGE_ONLY_ITEMS,
+ LARGE_ITEMS,
+ SMALL_ITEMS,
+} from "../templates/contentCards/demoitems";
+
+const VIEW_OPTIONS = [
+ "SmallImage",
+ "LargeImage",
+ "ImageOnly",
+ "Remote",
+] as const;
+type ViewOption = (typeof VIEW_OPTIONS)[number];
+
+const THEME_OPTIONS: Array<{
+ label: string;
+ value: ColorSchemeName;
+}> = [
+ { label: "Light", value: "light" },
+ { label: "Dark", value: "dark" },
+ { label: "System", value: null },
+];
+
+const ITEMS_BY_VIEW: Partial> = {
+ SmallImage: SMALL_ITEMS,
+ LargeImage: LARGE_ITEMS,
+ ImageOnly: IMAGE_ONLY_ITEMS,
+};
+
+const StyledText = ({ text }: { text: string }) => {
+ return {text};
+};
+
+const Header = ({
+ isLoading,
+ onTrackAction,
+ selectedView,
+ setSelectedView
+}: {
+ isLoading: boolean;
+ onTrackAction: () => void;
+ selectedView: ViewOption;
+ setSelectedView: (view: ViewOption) => void;
+}) => {
+ const [showPicker, setShowPicker] = useState(false);
+ const [selectedTheme, setSelectedTheme] = useState("System");
+ const [trackInput, setTrackInput] = useState("");
+ const colorScheme = useColorScheme();
+
+ const handleThemeChange = useCallback(
+ (theme: string, value: ColorSchemeName) => {
+ setSelectedTheme(theme);
+ Appearance.setColorScheme(value);
+ },
+ []
+ );
+
+ // Track action and refresh content cards
+ const handleTrackAction = useCallback(async () => {
+ if (!trackInput.trim()) {
+ return;
+ }
+
+ MobileCore.trackAction(trackInput);
+ await onTrackAction();
+ }, [trackInput, onTrackAction]);
+
+ const colors = colorScheme === "dark" ? Colors.dark : Colors.light;
+
+ return (
+
+ {/* View Picker */}
+
+ Select View Type
+ setShowPicker(true)}
+ >
+ {selectedView}
+
+
+
+ {/* Track Action Input */}
+
+ Track Action
+
+
+
+
+ {isLoading ? 'Loading...' : 'Track'}
+
+
+
+
+
+ {/* Theme Switcher */}
+
+ Theme
+
+ {THEME_OPTIONS.map(({ label, value }) => (
+ handleThemeChange(label, value)}
+ >
+
+ {label}
+
+
+ ))}
+
+
+
+ {/* View Picker Modal */}
+
+ setShowPicker(false)}>
+
+ {VIEW_OPTIONS.map((option) => (
+ {
+ setSelectedView(option);
+ setShowPicker(false);
+ }}
+ >
+ {option}
+
+ ))}
+ setShowPicker(false)}>
+ Cancel
+
+
+
+
+
+ );
+};
+
+const MemoHeader = memo(Header);
+
+const ContentCardsView = () => {
+ const [selectedView, setSelectedView] = useState('Remote');
+ const [trackInput, setTrackInput] = useState('');
+ const [containerSettings, setContainerSettings] = useState(null);
+ const colorScheme = useColorScheme();
+ const [currentPage, setCurrentPage] = useState(1);
+
+ const surface =
+ Platform.OS === "android"
+ ? "rn/android/remote_image"
+ : "rn/ios/remote_image";
+ const { content, isLoading, refetch } = useContentCardUI(surface);
+
+ // Load container settings for unread icon configuration
+ useEffect(() => {
+ const loadContainerSettings = async () => {
+ try {
+ const settings = await Messaging.getContentCardContainer(surface);
+ setContainerSettings(settings);
+ // Debug logging
+ // console.log('Container settings loaded:', JSON.stringify(settings, null, 2));
+ // console.log('isUnreadEnabled:', settings?.content?.isUnreadEnabled);
+ // console.log('unread_indicator:', settings?.content?.unread_indicator);
+ // console.log('unread_icon image URL:', settings?.content?.unread_indicator?.unread_icon?.image?.url);
+ // console.log('unread_icon darkUrl:', settings?.content?.unread_indicator?.unread_icon?.image?.darkUrl);
+ } catch (error) {
+ console.error('Failed to load container settings:', error);
+ }
+ };
+ loadContainerSettings();
+ }, [surface]);
+
+ const items = ITEMS_BY_VIEW[selectedView];
+
+ const colors = colorScheme === "dark" ? Colors.dark : Colors.light;
+
+ useEffect(() => {
+ MobileCore.trackAction("small_image");
+ }, []);
+
+ if (selectedView === 'Remote') {
+ return (
+ <>
+ {}}
+ selectedView={selectedView}
+ setSelectedView={setSelectedView}
+ />
+
+ >
+ );
+ }
+
+ return (
+ item.key}
+ renderItem={({ item }: any) => {
+ const node = (
+
+ );
+ return (
+
+
+ {item.customThemes ? (
+
+ {node}
+
+ ) : (
+ node
+ )}
+
+ );
+ }}
+ ListHeaderComponent={
+ {}}
+ selectedView={selectedView}
+ setSelectedView={setSelectedView}
+ />
+ }
+ contentContainerStyle={styles.listContent}
+ />
+ );
+};
+export default ContentCardsView;
+
+const SPACING = { s: 10, m: 20, l: 24 };
+
+const styles = StyleSheet.create({
+ infoText: {
+ color: "darkgray",
+ fontSize: 18,
+ paddingTop: SPACING.s,
+ paddingBottom: SPACING.s,
+ },
+ headerContainer: {
+ marginTop: 60,
+ marginBottom: 15,
+ alignItems: "center",
+ },
+ themeSwitcher: {
+ width: "80%",
+ borderRadius: 12,
+ padding: 4,
+ flexDirection: "row",
+ alignItems: "center",
+ justifyContent: "space-between",
+ },
+ section: {
+ marginHorizontal: SPACING.m,
+ marginBottom: SPACING.m,
+ },
+ themeOption: {
+ flex: 1,
+ paddingVertical: 8,
+ paddingHorizontal: 12,
+ borderRadius: 8,
+ marginHorizontal: 1,
+ alignItems: "center",
+ justifyContent: "center",
+ shadowOffset: { width: 0, height: 1 },
+ shadowRadius: 2,
+ },
+ themeOptionSelected: {
+ shadowColor: "#000",
+ shadowOpacity: 0.1,
+ elevation: 2,
+ },
+ themeOptionUnselected: {
+ backgroundColor: "transparent",
+ shadowColor: "transparent",
+ shadowOpacity: 0,
+ elevation: 0,
+ },
+ textTitle: {
+ fontSize: 16,
+ fontWeight: "600",
+ },
+ textBody: {
+ fontSize: 14,
+ lineHeight: SPACING.m,
+ },
+ textCaption: {
+ fontSize: 12,
+ fontStyle: "italic",
+ },
+ textLabel: {
+ fontSize: 14,
+ },
+ buttonNeutral: {
+ height: 50,
+ borderWidth: 1,
+ borderRadius: 5,
+ justifyContent: "center",
+ paddingHorizontal: SPACING.s,
+ },
+ buttonPrimary: {
+ backgroundColor: "#007AFF",
+ paddingHorizontal: 16,
+ paddingVertical: SPACING.s,
+ borderRadius: 8,
+ },
+ modalOverlay: {
+ flex: 1,
+ justifyContent: "center",
+ alignItems: "center",
+ backgroundColor: "rgba(0,0,0,0.5)",
+ },
+ modalCard: {
+ borderRadius: 10,
+ padding: SPACING.m,
+ backgroundColor: "white",
+ width: "80%",
+ },
+ modalOption: {
+ paddingVertical: SPACING.s,
+ borderBottomWidth: 1,
+ borderBottomColor: "#eee",
+ },
+ modalCancel: {
+ paddingVertical: SPACING.s,
+ marginTop: SPACING.s,
+ },
+ modalCancelText: {
+ color: "#FF3B30",
+ },
+ panel: {
+ borderRadius: SPACING.s,
+ borderWidth: 1,
+ padding: 15,
+ },
+ titleText: {
+ fontWeight: "600",
+ marginBottom: SPACING.s,
+ },
+ textCenter: {
+ textAlign: "center",
+ },
+ rowCenter: {
+ flexDirection: "row",
+ alignItems: "center",
+ },
+ trackRow: {
+ marginBottom: SPACING.s,
+ },
+ trackInput: {
+ flex: 1,
+ height: 40,
+ borderWidth: 1,
+ borderRadius: 8,
+ paddingHorizontal: 12,
+ marginRight: SPACING.s,
+ },
+ trackButtonText: {
+ color: "white",
+ fontWeight: "600",
+ },
+ emptyContainer: {
+ borderRadius: SPACING.s,
+ padding: SPACING.m,
+ margin: SPACING.m,
+ alignItems: "center",
+ },
+ listContent: {
+ paddingBottom: SPACING.l,
+ },
+});
\ No newline at end of file
diff --git a/apps/AEPSampleAppNewArchEnabled/app/MessagingView.tsx b/apps/AEPSampleAppNewArchEnabled/app/MessagingView.tsx
index 4d82cdc9d..95a115803 100644
--- a/apps/AEPSampleAppNewArchEnabled/app/MessagingView.tsx
+++ b/apps/AEPSampleAppNewArchEnabled/app/MessagingView.tsx
@@ -11,18 +11,13 @@ governing permissions and limitations under the License.
*/
import React from 'react';
-import {Button, Text, View, ScrollView} from 'react-native';
-import {MobileCore} from '@adobe/react-native-aepcore';
+import { Button, Text, View, ScrollView } from 'react-native';
+import { MobileCore } from '@adobe/react-native-aepcore';
import {
- Messaging,
- PersonalizationSchema,
- MessagingEdgeEventType,
- PropositionItem,
- Message,
- ContentCard,
- HTMLProposition,
- JSONPropositionItem
-} from '@adobe/react-native-aepmessaging'
+ Messaging,
+ PersonalizationSchema,
+ MessagingEdgeEventType
+} from '@adobe/react-native-aepmessaging';
import { MessagingProposition } from '@adobe/react-native-aepmessaging';
import styles from '../styles/styles';
import { useRouter } from 'expo-router';
@@ -30,7 +25,6 @@ import { useRouter } from 'expo-router';
const SURFACES = ['android-cbe-preview', 'cbe/json', 'android-cc'];
const SURFACES_WITH_CONTENT_CARDS = ['android-cc'];
-
const messagingExtensionVersion = async () => {
const version = await Messaging.extensionVersion();
console.log(`AdobeExperienceSDK: Messaging version: ${version}`);
@@ -43,8 +37,8 @@ const refreshInAppMessages = () => {
const setMessagingDelegate = () => {
Messaging.setMessagingDelegate({
- onDismiss: msg => console.log('dismissed!', msg),
- onShow: msg => {
+ onDismiss: (msg) => console.log('dismissed!', msg),
+ onShow: (msg) => {
console.log('show', msg);
msg.handleJavascriptMessage('myInappCallback', (content: string) => {
console.log('Received webview content in onShow:', content);
@@ -52,7 +46,7 @@ const setMessagingDelegate = () => {
},
shouldShowMessage: () => true,
shouldSaveMessage: () => true,
- urlLoaded: (url, message) => console.log(url, message),
+ urlLoaded: (url, message) => console.log(url, message)
});
console.log('messaging delegate set');
};
@@ -61,7 +55,7 @@ const getPropositionsForSurfaces = async () => {
console.log('getPropositionsForSurfaces', JSON.stringify(messages));
};
const trackAction = async () => {
- MobileCore.trackAction('iamjs', {full: true});
+ MobileCore.trackAction('iamjs', { full: true });
};
const updatePropositionsForSurfaces = async () => {
@@ -81,71 +75,83 @@ const getLatestMessage = async () => {
// this method can be used to track click interactions with content cards
const trackContentCardInteraction = async () => {
- const messages = await Messaging.getPropositionsForSurfaces(SURFACES_WITH_CONTENT_CARDS);
-
- for (const surface of SURFACES_WITH_CONTENT_CARDS) {
+ const messages = await Messaging.getPropositionsForSurfaces(
+ SURFACES_WITH_CONTENT_CARDS
+ );
+
+ for (const surface of SURFACES_WITH_CONTENT_CARDS) {
const propositions = messages[surface] || [];
for (const proposition of propositions) {
for (const propositionItem of proposition.items) {
if (propositionItem.schema === PersonalizationSchema.CONTENT_CARD) {
// Cast to ContentCard for the legacy tracking method
- Messaging.trackContentCardInteraction(proposition, propositionItem as any);
- console.log('trackContentCardInteraction', proposition, propositionItem);
+ Messaging.trackContentCardInteraction(
+ proposition,
+ propositionItem as any
+ );
+ console.log(
+ 'trackContentCardInteraction',
+ proposition,
+ propositionItem
+ );
}
}
}
}
-}
+};
// this method can be used to track display interactions with content cards
const trackContentCardDisplay = async () => {
- const messages = await Messaging.getPropositionsForSurfaces(SURFACES_WITH_CONTENT_CARDS);
+ const messages = await Messaging.getPropositionsForSurfaces(
+ SURFACES_WITH_CONTENT_CARDS
+ );
- for (const surface of SURFACES_WITH_CONTENT_CARDS) {
+ for (const surface of SURFACES_WITH_CONTENT_CARDS) {
const propositions = messages[surface] || [];
for (const proposition of propositions) {
for (const propositionItem of proposition.items) {
if (propositionItem.schema === PersonalizationSchema.CONTENT_CARD) {
// Cast to ContentCard for the legacy tracking method
- Messaging.trackContentCardDisplay(proposition, propositionItem as any);
+ Messaging.trackContentCardDisplay(
+ proposition,
+ propositionItem as any
+ );
console.log('trackContentCardDisplay', proposition, propositionItem);
}
}
}
}
-}
-
+};
// Method demonstrating unified tracking using PropositionItem methods
const unifiedTrackingExample = async () => {
- const messages = await Messaging.getPropositionsForSurfaces(SURFACES);
- for (const surface of SURFACES) {
+ const messages = await Messaging.getPropositionsForSurfaces(SURFACES);
+ for (const surface of SURFACES) {
const propositions = messages[surface] || [];
for (const proposition of propositions) {
- const propositionWrapper = new MessagingProposition(proposition);
- if (propositionWrapper.items.length > 0) {
- const propositionItem = propositionWrapper.items[0];
- propositionItem.track(MessagingEdgeEventType.DISPLAY);
+ for (const propositionItem of proposition.items) {
+ propositionItem.track(MessagingEdgeEventType.DISPLAY);
propositionItem.track('content_card_clicked', MessagingEdgeEventType.INTERACT, null);
}
}
}
-}
-
-
+};
function MessagingView() {
const router = useRouter();
return (
-
+
Messaging
-
+
-
-
-
+
+
+
);
diff --git a/apps/AEPSampleAppNewArchEnabled/app/OptimizeView.tsx b/apps/AEPSampleAppNewArchEnabled/app/OptimizeView.tsx
index 71a5d9ade..f2fa306dd 100644
--- a/apps/AEPSampleAppNewArchEnabled/app/OptimizeView.tsx
+++ b/apps/AEPSampleAppNewArchEnabled/app/OptimizeView.tsx
@@ -26,6 +26,7 @@ import {
Image,
TouchableOpacity,
Dimensions,
+ FlatList,
} from 'react-native';
import {RecyclerListView, DataProvider, LayoutProvider} from 'recyclerlistview';
import { useRouter } from 'expo-router';
diff --git a/apps/AEPSampleAppNewArchEnabled/app/_layout.tsx b/apps/AEPSampleAppNewArchEnabled/app/_layout.tsx
index 8c9217900..61a1c703b 100644
--- a/apps/AEPSampleAppNewArchEnabled/app/_layout.tsx
+++ b/apps/AEPSampleAppNewArchEnabled/app/_layout.tsx
@@ -1,13 +1,17 @@
-import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
-import * as SplashScreen from 'expo-splash-screen';
-import 'react-native-reanimated';
-import { Drawer } from 'expo-router/drawer';
+import {
+ DarkTheme,
+ DefaultTheme,
+ ThemeProvider,
+} from "@react-navigation/native";
+import * as SplashScreen from "expo-splash-screen";
+import "react-native-reanimated";
+import { Drawer } from "expo-router/drawer";
+import { Platform } from "react-native";
-
-import { useColorScheme } from '@/hooks/useColorScheme';
-import { MobileCore , LogLevel} from '@adobe/react-native-aepcore';
+import { useColorScheme } from "@/hooks/useColorScheme";
+import { MobileCore, LogLevel } from "@adobe/react-native-aepcore";
+import { useEffect } from "react";
import { Messaging } from '@adobe/react-native-aepmessaging';
-import { useEffect } from 'react';
// Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync();
@@ -18,30 +22,42 @@ export default function RootLayout() {
setTimeout(() => {
SplashScreen.hideAsync();
}, 3000);
-
+
useEffect(() => {
// If you need more customization, you can use the initOptions object and MobileCore.initialize() method.
-
+
// const initOptions = {
// appId: "YOUR-APP-ID", //optional,
// lifecycleAutomaticTrackingEnabled: true, //optional
// lifecycleAdditionalContextData: { "contextDataKey": "contextDataValue" }, //optional
// appGroupIOS: "group.com.your.app.identifier" //optional, for iOS app groups
// };
-
- // MobileCore.initialize(initOptions).then(() => {
+
+ // MobileCore.initialize(initOptions).then(() => {
// console.log("AEP SDK Initialized");
- // }).catch((error) => {
- // console.log("AEP SDK Initialization error", error);
+ // }).catch((error) => {
+ // console.log("AEP SDK Initialization error", error);
// });
-
+
// Initialize SDK once in App.tsx or the entry file.
// For functional components, use useEffect with an empty dependency array.
// For class components, call initializeWithAppId inside componentDidMount.
MobileCore.setLogLevel(LogLevel.DEBUG);
- MobileCore.initializeWithAppId("YOUR-APP-ID")
+ MobileCore.initializeWithAppId(
+ "3149c49c3910/473386a6e5b0/launch-6099493a8c97-development"
+ )
.then(() => {
console.log("AEP SDK Initialized");
+
+ // Messaging - Update propositions AFTER SDK is fully initialized
+ // Use platform-specific surface names
+ const surface = Platform.OS === 'android' ? 'rn/android/remote_image' : 'rn/ios/remote_image';
+ console.log("update propositions before for surface:", surface);
+ return Messaging.updatePropositionsForSurfaces([surface]);
+ })
+ .then(() => {
+ console.log("update propositions after - SUCCESS");
+ console.log("Propositions updated successfully in layout");
// // Set up messaging delegate after SDK initialization
// const unsubscribe = Messaging.setMessagingDelegate({
@@ -77,20 +93,42 @@ export default function RootLayout() {
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
-}
\ No newline at end of file
+}
diff --git a/apps/AEPSampleAppNewArchEnabled/app/index.tsx b/apps/AEPSampleAppNewArchEnabled/app/index.tsx
index 97d953ba8..53cde1364 100644
--- a/apps/AEPSampleAppNewArchEnabled/app/index.tsx
+++ b/apps/AEPSampleAppNewArchEnabled/app/index.tsx
@@ -11,38 +11,39 @@ governing permissions and limitations under the License.
import React from 'react';
import { View, Button } from 'react-native';
-import { useNavigation } from 'expo-router';
+import { useRouter } from 'expo-router';
export default function HomeScreen() {
- const navigation = useNavigation();
+ const router = useRouter();
return (
-