window.onload = function() { setTimeout(function() { const MindFlyAdmin = { init() { // Inject CSS for broadcast overlay this.injectCSS(); this.AdminBarModule.init(); this.StreamButtonModule.init(); this.OfflineMessageModule.init(); }, injectCSS() { const style = document.createElement('style'); // Add font face definition style.textContent = ` @font-face { font-family: 'MADE Outer Sans Bold'; src: url('https://d2klnrbnvob1h4.cloudfront.net/assets/fonts/MADEOuterSans-Black/MADE+Outer+Sans+Black+PERSONAL+USE.otf') format('opentype'); font-weight: bold; font-style: normal; } [data-testid="broadcast-overlay-wrapper"] { font-family: 'MADE Outer Sans Bold', sans-serif; } `; // Append the style to the document head document.head.appendChild(style); }, OfflineMessageModule: { init() { // Use MutationObserver to detect dynamically added messages const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.addedNodes.length) { this.findAndRemoveOfflineMessage(); } }); }); // Start observing the document body observer.observe(document.body, { childList: true, subtree: true }); // Initial check for existing message this.findAndRemoveOfflineMessage(); }, findAndRemoveOfflineMessage() { // Find all text nodes const walker = document.createTreeWalker( document.body, NodeFilter.SHOW_TEXT, null, false ); while (walker.nextNode()) { const node = walker.currentNode; if (node.textContent.trim() === 'Your Channel is Offline') { // Find the parent div to remove let parentDiv = node.parentElement; while (parentDiv && parentDiv.tagName !== 'DIV') { parentDiv = parentDiv.parentElement; } // If we found a parent div, remove its parent as well if (parentDiv && parentDiv.parentElement) { parentDiv.parentElement.remove(); } } } } }, StreamButtonModule: { init() { // Use MutationObserver to detect dynamically added buttons const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.addedNodes.length) { this.findAndModifyStreamButtons(); } }); }); // Start observing the document body observer.observe(document.body, { childList: true, subtree: true }); // Initial check for existing buttons this.findAndModifyStreamButtons(); }, findAndModifyStreamButtons() { // Find all buttons containing "Stream" text const buttons = Array.from(document.getElementsByTagName('button')).filter( button => button.textContent.trim() === 'Stream' ); buttons.forEach(button => { // Only modify if not already processed if (!button.dataset.mindFlyProcessed) { button.dataset.mindFlyProcessed = 'true'; this.modifyStreamButton(button); } }); }, modifyStreamButton(button) { button.addEventListener('click', async (e) => { e.preventDefault(); e.stopPropagation(); // Create container for the streamer const container = document.createElement('div'); container.style.cssText = ` position: fixed; bottom: 20px; left: 20px; z-index: 9999; background: black; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); `; // Create close button const closeButton = document.createElement('button'); closeButton.innerHTML = '×'; closeButton.style.cssText = ` position: absolute; top: 10px; right: 10px; background: rgba(0, 0, 0, 0.5); color: white; border: none; font-size: 18px; cursor: pointer; width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; z-index: 1; `; // Create streamer container const streamerContainer = document.createElement('div'); streamerContainer.style.cssText = ` width: 320px; height: 180px; `; // Load dependencies and create streamer await this.loadDependencies(); // Get customer slug from URL const slug = MindFlyAdmin.AdminBarModule.getSlugFromUrl(); // Create whip-streamer element const streamer = document.createElement('whip-streamer'); streamer.id = 'streamer'; streamer.style.cssText = 'width: 100%; height: 100%;'; // Create and inject the script tag const script = document.createElement('script'); script.src = `https://backend.mindfly.digital/studio/whip-streamer.js?customer=${slug}`; script.async = true; // Add elements to DOM streamerContainer.appendChild(streamer); container.appendChild(streamerContainer); container.appendChild(closeButton); document.body.appendChild(container); document.head.appendChild(script); // Handle closing closeButton.onclick = () => { container.remove(); script.remove(); }; }); }, async loadDependencies() { // Load Axios if not already loaded if (!window.axios) { await this.loadScript('https://cdnjs.cloudflare.com/ajax/libs/axios/1.6.2/axios.min.js'); } }, loadScript(url) { return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = url; script.onload = resolve; script.onerror = reject; document.head.appendChild(script); }); } }, AdminBarModule: { init() { const maxRetries = 5; const retryInterval = 500; // 500ms between retries const attemptInit = (retriesLeft) => { var logarr = ["Debug log:"]; const adminBar = document.getElementById('admin-bar'); if (!adminBar) { if (retriesLeft > 0) { console.log(`Admin bar not found. Retrying... (${retriesLeft} attempts left)`); logarr.push(`Admin bar not found. Retrying... (${retriesLeft} attempts left)`); setTimeout(() => attemptInit(retriesLeft - 1), retryInterval); } else { console.error('Could not find admin bar after multiple attempts'); logarr.push(`Could not find admin bar after multiple attempts`); } return; } const targetButton = this.findTargetButton(adminBar); if (!targetButton) { if (retriesLeft > 0) { console.log(`Target button not found. Retrying... (${retriesLeft} attempts left)`); logarr.push(`Target button not found. Retrying... (${retriesLeft} attempts left)`); setTimeout(() => attemptInit(retriesLeft - 1), retryInterval); } else { console.error('Could not find target button after multiple attempts'); logarr.push('Could not find target button after multiple attempts'); } return; } // Proceed with adding buttons const mindFlyButton = this.createMindFlyButton(targetButton); targetButton.parentNode.insertBefore(mindFlyButton, targetButton); const multiStreamButton = this.createMultiStreamButton(targetButton); targetButton.parentNode.insertBefore(multiStreamButton, targetButton); var logtxt = logarr.join(' | '); // alert(logtxt); }; // Start the initial attempt attemptInit(maxRetries); }, findTargetButton(adminBar) { return Array.from(adminBar.getElementsByTagName('button')) .find(button => button.textContent.includes('Page') || button.textContent.includes('Channel')); }, createMindFlyButton(targetButton) { const newButton = targetButton.cloneNode(true); this.updateButtonIcon(newButton); this.updateButtonText(newButton); newButton.onclick = this.createIframeOverlay; return newButton; }, updateButtonIcon(button) { const videoIconSvg = ` `; const svgContainer = button.querySelector('span svg').parentElement; if (svgContainer) { svgContainer.innerHTML = videoIconSvg; svgContainer.setAttribute('name', 'video-camera'); } }, updateButtonText(button) { const walkNodes = document.createTreeWalker( button, NodeFilter.SHOW_TEXT, null, false ); let node; while (node = walkNodes.nextNode()) { if (node.textContent.includes('Page') || node.textContent.includes('Channel')) { node.textContent = node.textContent.replace(/Page|Channel/, 'MindFly'); } } }, getSlugFromUrl() { const path = window.location.pathname; const slug = path.replace(/^\/|\/$/g, '').split('/')[0]; return slug || ''; }, createIframeOverlay() { const overlay = document.createElement('div'); overlay.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.7); display: flex; justify-content: center; align-items: center; z-index: 9999; `; const iframe = document.createElement('iframe'); iframe.src = `https://backend.mindfly.digital/dashboard/manager?customer=${encodeURIComponent(MindFlyAdmin.AdminBarModule.getSlugFromUrl())}`; iframe.style.cssText = ` width: 90%; height: 90%; border: none; border-radius: 8px; background: white; `; const closeButton = document.createElement('button'); closeButton.innerHTML = '×'; closeButton.style.cssText = ` position: absolute; top: 20px; right: 20px; background: white; border: none; font-size: 24px; cursor: pointer; width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; `; closeButton.onclick = () => overlay.remove(); overlay.onclick = (e) => { if (e.target === overlay) overlay.remove(); }; overlay.appendChild(iframe); overlay.appendChild(closeButton); document.body.appendChild(overlay); }, createMultiStreamButton(targetButton) { const newButton = targetButton.cloneNode(true); this.updateMultiStreamButtonIcon(newButton); this.updateMultiStreamButtonText(newButton); newButton.onclick = this.createMultiStreamIframeOverlay; return newButton; }, updateMultiStreamButtonIcon(button) { const multiStreamIconSvg = ` `; const svgContainer = button.querySelector('span svg').parentElement; if (svgContainer) { svgContainer.innerHTML = multiStreamIconSvg; svgContainer.setAttribute('name', 'multi-stream'); } }, updateMultiStreamButtonText(button) { const walkNodes = document.createTreeWalker( button, NodeFilter.SHOW_TEXT, null, false ); let node; while (node = walkNodes.nextNode()) { if (node.textContent.includes('Page') || node.textContent.includes('Channel')) { node.textContent = node.textContent.replace(/Page|Channel/, 'Multi-Stream'); } } }, createMultiStreamIframeOverlay() { const overlay = document.createElement('div'); overlay.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.7); display: flex; justify-content: center; align-items: center; z-index: 9999; `; const iframe = document.createElement('iframe'); iframe.src = 'https://backend.mindfly.digital/maestro/uploader'; iframe.style.cssText = ` width: 90%; height: 90%; border: none; border-radius: 8px; background: white; `; const closeButton = document.createElement('button'); closeButton.innerHTML = '×'; closeButton.style.cssText = ` position: absolute; top: 20px; right: 20px; background: white; border: none; font-size: 24px; cursor: pointer; width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; `; closeButton.onclick = () => overlay.remove(); overlay.onclick = (e) => { if (e.target === overlay) overlay.remove(); }; overlay.appendChild(iframe); overlay.appendChild(closeButton); document.body.appendChild(overlay); } } }; MindFlyAdmin.init(); }, 1000); };