'use client'; import React from 'react'; import { useCallback, useEffect } from 'react'; import { useMobileIframeHandler } from '../hooks'; import { useAppDispatch, useAppSelector } from '../redux/hooks'; import { setComponents, setDataSources, setDesignMode, setDraggingActive, setPlaceholders, setResponsive, setSelectedComponentId, setSelectedPlaceholder, setSelectedWidget } from '../redux/reducers/widget'; import { LoggerPopup } from './logger-popup'; import { LoggerProvider } from '../hooks/use-logger-context'; import { ToastContainer } from './toast'; import * as Sentry from '@sentry/nextjs'; import { initSentry } from '../sentry'; export default function ClientRoot({ children, sessionId }: { children: React.ReactNode; sessionId?: string; }) { const { preventPageRender } = useMobileIframeHandler({ sessionId: sessionId || '' }); const { components } = useAppSelector((state) => state.widget); const dispatch = useAppDispatch(); const postMessage = (message: { type: string; data: Record; }) => { window.parent.postMessage(message, '*'); }; const handleWidgetMessage = useCallback( (event: MessageEvent) => { if (event.data.type === 'UPDATE_COMPONENTS') { const { components } = event.data.data; dispatch(setComponents(components)); } else if (event.data.type === 'UPDATE_WIDGET_SYSTEM') { const { responsive, designMode, selectedComponentId, placeholders, dataSources } = event.data.data; dispatch(setResponsive(responsive)); dispatch(setDesignMode(designMode)); dispatch(setSelectedComponentId(selectedComponentId)); dispatch(setPlaceholders(placeholders)); dispatch(setDataSources(dataSources)); } else if (event.data.type === 'SELECT_PLACEHOLDER') { const { placeholderSlug } = event.data.data; dispatch(setSelectedPlaceholder(placeholderSlug)); } else if (event.data.type === 'SELECT_WIDGET') { const { widgetSlug } = event.data.data; dispatch(setSelectedWidget(widgetSlug)); postMessage({ type: 'SELECT_COMPONENT', data: { componentId: null } }); } else if (event.data.type === 'DRAG_START') { dispatch(setDraggingActive(true)); } else if (event.data.type === 'DRAG_END') { dispatch(setDraggingActive(false)); } else if (event.data.type === 'GET_DROP_TARGET') { const { x, y, component } = event.data.data; const elements = document.elementsFromPoint(x, y); const dropTargetId = elements .find((element) => element.hasAttribute('data-component')) ?.getAttribute('data-id'); postMessage({ type: 'DROP_TARGET_RESPONSE', data: { targetId: dropTargetId, component } }); } else if (event.data.type === 'SET_COOKIE') { const { key, value } = event.data.data.value; if (key && value) { let cookieString = ''; if (window.parent !== window) { cookieString = `${key}=${value}; path=/; SameSite=None; Secure`; } else if (key === 'widget_builder') { cookieString = `${key}=false; path=/; SameSite=None; Secure`; } if (cookieString) { document.cookie = cookieString; } } } }, [dispatch, components] ); useEffect(() => { window.addEventListener('message', handleWidgetMessage); if (window.parent === window) { document.cookie = 'widget_builder=false; path=/; SameSite=None; Secure'; } return () => { window.removeEventListener('message', handleWidgetMessage); }; }, [handleWidgetMessage]); const initializeSentry = async () => { const response = await fetch('/api/sentry', { next: { revalidate: 0 } }); const data = await response.json(); const options = { dsn: data.dsn }; initSentry('Client', options); }; useEffect(() => { if (!Sentry.isInitialized()) { initializeSentry(); } }, []); if (preventPageRender) { return null; } return ( {children} ); }