(function(win, doc) { // Centralized messaging system const TBBridgeMessaging = (function() { // Constants for messaging const TB_AI = { INITIALIZE: 'TB_AI_INITIALIZE', INITIALIZED: 'TB_AI_INITIALIZED', ERROR: 'TB_AI_ERROR' }; // Normalize origins and build a set const normalize = (o) => { try { const u = new URL(o); return `${u.protocol}//${u.hostname}${u.port ? ':' + u.port : ''}`; } catch { return ''; } }; // Parse message data function parseMessage(data) { if (typeof data === 'string') { try { return JSON.parse(data); } catch (e) { console.error('[Bridge] Failed to parse message data:', e); return null; } } return data; // Already an object } // Safe message sending function sendMessage(target, data, origin = '*') { try { // Always stringify to ensure compatibility const message = JSON.stringify(data); if (target && target.postMessage) { target.postMessage(message, origin); return true; } } catch (err) { console.error('[Bridge] Error sending message:', err); } return false; } // Return public API return { TB_AI, normalize, parseMessage, sendMessage }; })(); // Get bridge URL from PHP config const tbAiBridgeUrl = ''.split(',').map(url => url.trim()); if (typeof angular !== 'undefined') { // Get plan settings from config angular.module('app').constant('PLAN_SETTINGS', '{"userLimitColumns":{"enable_pdf":"allow_pdf_page","enable_pdf_filler":"allow_pdf_form","enable_pipe_js":"allow_pipe_js","enable_allow_restore":"allow_restore","enable_incoming_webhook":"allow_incoming_webhook","enable_email_catchers":"allow_incoming_webhook","enable_sms":"allow_sms","enable_field_auditor":"allow_field_auditor","allow_data_bridge":"allow_data_bridge","allow_plugin":"allow_plugin","allow_dynamic_field":"allow_dynamic_field","enable2fa":"allow_two_factor","enable_support":"priority_support","allow_search_v2":"allow_search_v2","enable_optimize_new_table":"allow_optimize_table"},"bypassSubscriptionPlanLimit":""}'); } const allowedOrigins = new Set(tbAiBridgeUrl.map(TBBridgeMessaging.normalize)); const bridgePath = '/js/component-selector-bridge.js'; let loaded = false; // Create message handler win.addEventListener('message', (event) => { if (!checkNested(event, 'data') || !event.data) return; // Parse and validate message const data = TBBridgeMessaging.parseMessage(event.data); if (!data || data.action !== TBBridgeMessaging.TB_AI.INITIALIZE) return; // Validate origin const parentOrigin = TBBridgeMessaging.normalize(event.origin); if (!allowedOrigins.has(parentOrigin)) { console.warn('[Bridge] Untrusted origin:', parentOrigin); return; } // Handle already loaded case, but allow reinitialization for app changes if (loaded) { // Don't just return - we want to reinitialize the bridge // for new apps or when the app changes // console.log('[Bridge] Script already loaded, sending initialization confirmation'); TBBridgeMessaging.sendMessage( event.source, { type: TBBridgeMessaging.TB_AI.INITIALIZED, note: 'already_initialized' }, parentOrigin ); // return; // We continue execution to allow the script to refresh handlers } // Load the bridge script const s = doc.createElement('script'); s.src = parentOrigin.replace(/\/+$/, '') + bridgePath; s.async = true; // Handle successful load s.onload = () => { loaded = true; console.log('[Bridge] Loaded:', s.src); // Add a delay to ensure jQuery is available setTimeout(() => { TBBridgeMessaging.sendMessage( event.source, { type: TBBridgeMessaging.TB_AI.INITIALIZED, status: 'success' }, parentOrigin ); }, 500); }; // Handle load error s.onerror = () => { TBBridgeMessaging.sendMessage( event.source, { type: TBBridgeMessaging.TB_AI.ERROR, error: 'load_failed' }, parentOrigin ); }; // Append the script (doc.head || doc.body || doc.documentElement).appendChild(s); }); })(window, document);