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);
};