'use client'; import { useEffect, useRef, useState } from 'react'; import { useSession } from 'next-auth/react'; export interface ResponsiveIframeProps { src: string; title?: string; token?: string; className?: string; style?: React.CSSProperties; hideUntilLoad?: boolean; allowFullScreen?: boolean; scrolling?: boolean; heightOffset?: number; } export default function ResponsiveIframe({ src, title = 'Embedded content', token, className = '', style = {}, hideUntilLoad = false, allowFullScreen = false, scrolling = true, heightOffset = 0, }: ResponsiveIframeProps) { const [height, setHeight] = useState(0); const [loaded, setLoaded] = useState(false); const [authError, setAuthError] = useState(false); const iframeRef = useRef(null); const silentAuthRef = useRef(null); const silentAuthTimerRef = useRef(null); const { data: session } = useSession(); // Append token to src if provided const fullSrc = token ? `${src}${src.includes('?') ? '&' : '?'}token=${token}` : src; // Handle silent authentication refresh useEffect(() => { // Setup silent authentication check every 15 minutes const setupSilentAuth = () => { if (silentAuthTimerRef.current) { clearTimeout(silentAuthTimerRef.current); } // Create a hidden iframe to check authentication status silentAuthTimerRef.current = setTimeout(() => { console.log('Running silent authentication check'); // Create the silent auth iframe if it doesn't exist if (silentAuthRef.current && !silentAuthRef.current.src) { silentAuthRef.current.src = '/silent-refresh'; } // Setup next check setupSilentAuth(); }, 15 * 60 * 1000); // 15 minutes }; // Handle messages from the silent auth iframe const handleAuthMessage = (event: MessageEvent) => { if (event.data && event.data.type === 'AUTH_STATUS') { console.log('Received auth status:', event.data); if (event.data.status === 'UNAUTHENTICATED') { console.error('Silent authentication failed - user is not authenticated'); setAuthError(true); // Force immediate refresh if (silentAuthRef.current) { silentAuthRef.current.src = '/silent-refresh'; } } else if (event.data.status === 'AUTHENTICATED') { console.log('Silent authentication successful'); setAuthError(false); } } }; window.addEventListener('message', handleAuthMessage); setupSilentAuth(); // Cleanup return () => { window.removeEventListener('message', handleAuthMessage); if (silentAuthTimerRef.current) { clearTimeout(silentAuthTimerRef.current); } }; }, []); // Adjust iframe height based on window size useEffect(() => { const updateHeight = () => { const viewportHeight = window.innerHeight; const newHeight = viewportHeight - heightOffset; setHeight(newHeight > 0 ? newHeight : 0); }; updateHeight(); window.addEventListener('resize', updateHeight); return () => { window.removeEventListener('resize', updateHeight); }; }, [heightOffset]); // Handle hash changes by updating iframe source useEffect(() => { const handleHashChange = () => { const iframe = iframeRef.current; if (iframe && iframe.src) { const url = new URL(iframe.src); // If there's a hash in the parent window's URL if (window.location.hash) { url.hash = window.location.hash; iframe.src = url.toString(); } } }; window.addEventListener('hashchange', handleHashChange); return () => { window.removeEventListener('hashchange', handleHashChange); }; }, []); return ( <> {/* Hidden iframe for silent authentication */}