diff --git a/src/embedded/components/IterableEmbeddedView.tsx b/src/embedded/components/IterableEmbeddedView.tsx
index 7234e3904..365d6029d 100644
--- a/src/embedded/components/IterableEmbeddedView.tsx
+++ b/src/embedded/components/IterableEmbeddedView.tsx
@@ -1,5 +1,5 @@
import { useMemo } from 'react';
-import { View, Text } from 'react-native';
+import { View, Text, Image } from 'react-native';
import { IterableEmbeddedViewType } from '../enums/IterableEmbeddedViewType';
@@ -45,40 +45,14 @@ export const IterableEmbeddedView = ({
}
}, [viewType]);
- const { parsedStyles } = useEmbeddedView(viewType, props);
+ const { media } = useEmbeddedView(viewType, props);
return Cmp ? (
-
- parsedStyles.backgroundColor: {String(parsedStyles.backgroundColor)}
-
- parsedStyles.borderColor: {String(parsedStyles.borderColor)}
- parsedStyles.borderWidth: {parsedStyles.borderWidth}
-
- parsedStyles.borderCornerRadius: {parsedStyles.borderCornerRadius}
-
-
- parsedStyles.primaryBtnBackgroundColor:{' '}
- {String(parsedStyles.primaryBtnBackgroundColor)}
-
-
- parsedStyles.primaryBtnTextColor:{' '}
- {String(parsedStyles.primaryBtnTextColor)}
-
-
- parsedStyles.secondaryBtnBackgroundColor:{' '}
- {String(parsedStyles.secondaryBtnBackgroundColor)}
-
-
- parsedStyles.secondaryBtnTextColor:{' '}
- {String(parsedStyles.secondaryBtnTextColor)}
-
-
- parsedStyles.titleTextColor: {String(parsedStyles.titleTextColor)}
-
-
- parsedStyles.bodyTextColor: {String(parsedStyles.bodyTextColor)}
-
+ media.url: {media.url}
+ media.caption: {media.caption}
+ media.shouldShow: {media.shouldShow ? 'true' : 'false'}
+ {media.url ? : null}
) : null;
diff --git a/src/embedded/hooks/useEmbeddedView/getMedia.test.ts b/src/embedded/hooks/useEmbeddedView/getMedia.test.ts
new file mode 100644
index 000000000..b4e793ffd
--- /dev/null
+++ b/src/embedded/hooks/useEmbeddedView/getMedia.test.ts
@@ -0,0 +1,136 @@
+import { getMedia } from './getMedia';
+import { IterableEmbeddedViewType } from '../../enums';
+import type { IterableEmbeddedMessage } from '../../types/IterableEmbeddedMessage';
+
+const minimalMessage: IterableEmbeddedMessage = {
+ metadata: { messageId: 'msg-1', placementId: 1 },
+};
+
+describe('getMedia', () => {
+ describe('viewType Notification', () => {
+ it('returns no media regardless of message content', () => {
+ const result = getMedia(IterableEmbeddedViewType.Notification, minimalMessage);
+
+ expect(result).toEqual({ url: null, caption: null, shouldShow: false });
+ });
+
+ it('returns no media even when message has mediaUrl and caption', () => {
+ const message: IterableEmbeddedMessage = {
+ ...minimalMessage,
+ elements: {
+ mediaUrl: 'https://example.com/image.png',
+ mediaUrlCaption: 'Example caption',
+ },
+ };
+
+ const result = getMedia(IterableEmbeddedViewType.Notification, message);
+
+ expect(result).toEqual({ url: null, caption: null, shouldShow: false });
+ });
+ });
+
+ describe('viewType Card', () => {
+ it('returns url and caption from message.elements, shouldShow true when url is non-empty', () => {
+ const message: IterableEmbeddedMessage = {
+ ...minimalMessage,
+ elements: {
+ mediaUrl: 'https://example.com/photo.jpg',
+ mediaUrlCaption: 'A nice photo',
+ },
+ };
+
+ const result = getMedia(IterableEmbeddedViewType.Card, message);
+
+ expect(result).toEqual({
+ url: 'https://example.com/photo.jpg',
+ caption: 'A nice photo',
+ shouldShow: true,
+ });
+ });
+
+ it('returns url only (caption null) when message has no mediaUrlCaption', () => {
+ const message: IterableEmbeddedMessage = {
+ ...minimalMessage,
+ elements: { mediaUrl: 'https://example.com/img.png' },
+ };
+
+ const result = getMedia(IterableEmbeddedViewType.Card, message);
+
+ expect(result).toEqual({
+ url: 'https://example.com/img.png',
+ caption: null,
+ shouldShow: true,
+ });
+ });
+
+ it('returns shouldShow false when mediaUrl is empty string', () => {
+ const message: IterableEmbeddedMessage = {
+ ...minimalMessage,
+ elements: { mediaUrl: '', mediaUrlCaption: 'Caption' },
+ };
+
+ const result = getMedia(IterableEmbeddedViewType.Card, message);
+
+ expect(result.url).toBe('');
+ expect(result.caption).toBe('Caption');
+ expect(result.shouldShow).toBe(false);
+ });
+
+ it('returns null url/caption and shouldShow false when message has no elements', () => {
+ const result = getMedia(IterableEmbeddedViewType.Card, minimalMessage);
+
+ expect(result).toEqual({ url: null, caption: null, shouldShow: false });
+ });
+
+ it('returns null url/caption when elements exist but mediaUrl is undefined', () => {
+ const message: IterableEmbeddedMessage = {
+ ...minimalMessage,
+ elements: { title: 'Title', body: 'Body' },
+ };
+
+ const result = getMedia(IterableEmbeddedViewType.Card, message);
+
+ expect(result).toEqual({ url: null, caption: null, shouldShow: false });
+ });
+ });
+
+ describe('viewType Banner', () => {
+ it('returns url and caption from message.elements, shouldShow true when url is non-empty', () => {
+ const message: IterableEmbeddedMessage = {
+ ...minimalMessage,
+ elements: {
+ mediaUrl: 'https://example.com/banner.png',
+ mediaUrlCaption: 'Banner caption',
+ },
+ };
+
+ const result = getMedia(IterableEmbeddedViewType.Banner, message);
+
+ expect(result).toEqual({
+ url: 'https://example.com/banner.png',
+ caption: 'Banner caption',
+ shouldShow: true,
+ });
+ });
+
+ it('returns null url/caption and shouldShow false when message has no elements', () => {
+ const result = getMedia(IterableEmbeddedViewType.Banner, minimalMessage);
+
+ expect(result).toEqual({ url: null, caption: null, shouldShow: false });
+ });
+ });
+
+ describe('return shape', () => {
+ it('returns an object with url, caption, and shouldShow', () => {
+ const result = getMedia(IterableEmbeddedViewType.Card, minimalMessage);
+
+ expect(Object.keys(result)).toHaveLength(3);
+ expect(result).toHaveProperty('url');
+ expect(result).toHaveProperty('caption');
+ expect(result).toHaveProperty('shouldShow');
+ expect(typeof result.shouldShow).toBe('boolean');
+ expect(result.url === null || typeof result.url === 'string').toBe(true);
+ expect(result.caption === null || typeof result.caption === 'string').toBe(true);
+ });
+ });
+});
diff --git a/src/embedded/hooks/useEmbeddedView/getMedia.ts b/src/embedded/hooks/useEmbeddedView/getMedia.ts
new file mode 100644
index 000000000..7260ca407
--- /dev/null
+++ b/src/embedded/hooks/useEmbeddedView/getMedia.ts
@@ -0,0 +1,31 @@
+import type { IterableEmbeddedMessage } from '../../types/IterableEmbeddedMessage';
+import { IterableEmbeddedViewType } from '../../enums';
+
+/**
+ * This function is used to get the media to render for a given embedded view
+ * type and message.
+ *
+ * @param viewType - The type of view to render.
+ * @param message - The message to render.
+ * @returns The media to render.
+ *
+ * @example
+ * const media = getMedia(IterableEmbeddedViewType.Notification, message);
+ * console.log(media.url);
+ * console.log(media.caption);
+ * console.log(media.shouldShow ? 'true' : 'false');
+ */
+export const getMedia = (
+ /** The type of view to render. */
+ viewType: IterableEmbeddedViewType,
+ /** The message to render. */
+ message: IterableEmbeddedMessage
+) => {
+ if (viewType === IterableEmbeddedViewType.Notification) {
+ return { url: null, caption: null, shouldShow: false };
+ }
+ const url = message.elements?.mediaUrl ?? null;
+ const caption = message.elements?.mediaUrlCaption ?? null;
+ const shouldShow = !!url && url.length > 0;
+ return { url, caption, shouldShow };
+};
diff --git a/src/embedded/hooks/useEmbeddedView/useEmbeddedView.ts b/src/embedded/hooks/useEmbeddedView/useEmbeddedView.ts
index eb4997782..1ed04d3ee 100644
--- a/src/embedded/hooks/useEmbeddedView/useEmbeddedView.ts
+++ b/src/embedded/hooks/useEmbeddedView/useEmbeddedView.ts
@@ -1,6 +1,8 @@
import { useMemo } from 'react';
+
import { IterableEmbeddedViewType } from '../../enums';
import type { IterableEmbeddedComponentProps } from '../../types/IterableEmbeddedComponentProps';
+import { getMedia } from './getMedia';
import { getStyles } from './getStyles';
/**
@@ -11,7 +13,7 @@ import { getStyles } from './getStyles';
* @returns The embedded view.
*
* @example
- * const \{ parsedStyles \} = useEmbeddedView(IterableEmbeddedViewType.Notification, \{
+ * const \{ media, parsedStyles \} = useEmbeddedView(IterableEmbeddedViewType.Notification, \{
* message,
* config,
* onButtonClick,
@@ -20,6 +22,8 @@ import { getStyles } from './getStyles';
*
* return (
*
+ * \{media.url\}
+ * \{media.caption\}
* \{parsedStyles.backgroundColor\}
*
* );
@@ -30,13 +34,18 @@ export const useEmbeddedView = (
/** The props for the embedded view. */
{
config,
+ message,
}: IterableEmbeddedComponentProps
) => {
const parsedStyles = useMemo(() => {
return getStyles(viewType, config);
}, [viewType, config]);
+ const media = useMemo(() => {
+ return getMedia(viewType, message);
+ }, [viewType, message]);
return {
parsedStyles,
+ media,
};
};