Files
mirotalk/public/js/brand.js
T

334 lines
14 KiB
JavaScript

'use strict';
// Brand
const brandDataKey = 'brandDataP2P';
const brandData = window.sessionStorage.getItem(brandDataKey);
// Html pages
const landingTitle = document.getElementById('landingTitle');
const newCallTitle = document.getElementById('newCallTitle');
const newCallRoomTitle = document.getElementById('newCallRoomTitle');
const newCallRoomDescription = document.getElementById('newCallRoomDescription');
const loginTitle = document.getElementById('loginTitle');
const loginHeading = document.getElementById('loginHeading');
const loginDescription = document.getElementById('loginDescription');
const loginButtonLabel = document.getElementById('loginButtonLabel');
const joinRoomTitle = document.getElementById('joinRoomTitle');
const joinRoomButtonLabel = document.getElementById('joinRoomButtonLabel');
const waitingRoomTitle = document.getElementById('waitingRoomTitle');
const waitingRoomHeading = document.getElementById('waitingRoomHeading');
const waitingRoomDescription = document.getElementById('waitingRoomDescription');
const waitingRoomStatus = document.getElementById('waitingStatus');
const waitingRoomHostLink = document.getElementById('waitingRoomHostLink');
const waitingRoomLoginLink = document.getElementById('waitingRoomLoginLink');
const privacyPolicyTitle = document.getElementById('privacyPolicyTitle');
const stunTurnTitle = document.getElementById('stunTurnTitle');
const clientTitle = document.getElementById('clientTitle');
const notFoundTitle = document.getElementById('stunTurnTitle');
const shortcutIcon = document.getElementById('shortcutIcon');
const appleTouchIcon = document.getElementById('appleTouchIcon');
const appTitle = document.getElementById('appTitle');
const appDescription = document.getElementById('appDescription');
const appJoinDescription = document.getElementById('appJoinDescription');
const joinRoomBtn = document.getElementById('joinRoomButton');
const customizeRoomBtn = document.getElementById('customizeRoomButton');
const appJoinLastRoom = document.getElementById('appJoinLastRoom');
const topSponsors = document.getElementById('topSponsors');
const features = document.getElementById('features');
const browsers = document.getElementById('browsers');
const teams = document.getElementById('teams');
const tryEasier = document.getElementById('tryEasier');
const poweredBy = document.getElementById('poweredBy');
const sponsors = document.getElementById('sponsors');
const advertisers = document.getElementById('advertisers');
const supportUs = document.getElementById('supportUs');
const footer = document.getElementById('footer');
//...
// Brand customizations...
let brand = {
app: {
language: 'en',
name: 'MiroTalk',
title: 'MiroTalk<br />Free browser based Real-time video calls.<br />Simple, Secure, Fast.',
description:
'Start your next video call with a single click. No download, plug-in, or login is required. Just get straight to talking, messaging, and sharing your screen.',
joinDescription: 'Pick a room name.<br />How about this one?',
joinButtonLabel: 'JOIN ROOM',
customizeRoomButtonLabel: 'CUSTOMIZE ROOM',
joinLastLabel: 'Your recent room:',
},
site: {
shortcutIcon: '../images/logo.svg',
appleTouchIcon: '../images/logo.svg',
landingTitle: 'MiroTalk a Free Secure Video Calls, Chat & Screen Sharing.',
newCallTitle: 'MiroTalk a Free Secure Video Calls, Chat & Screen Sharing.',
newCallRoomTitle: 'Pick name. <br />Share URL. <br />Start conference.',
newCallRoomDescription:
"Each room has its disposable URL. Just pick a room name and share your custom URL. It's that easy.",
loginTitle: 'MiroTalk - Host Protected login required.',
loginHeading: 'Welcome back',
loginDescription: 'Enter your credentials to continue.',
loginButtonLabel: 'Login',
joinRoomTitle: 'Pick name.<br />Share URL.<br />Start conference.',
joinRoomButtonLabel: 'JOIN ROOM',
clientTitle: 'MiroTalk WebRTC Video call, Chat Room & Screen Sharing.',
privacyPolicyTitle: 'MiroTalk - privacy and policy.',
stunTurnTitle: 'Test Stun/Turn Servers.',
notFoundTitle: 'MiroTalk - 404 Page not found.',
waitingRoomTitle: 'MiroTalk - Waiting for host to start the meeting',
waitingRoomHeading: 'Waiting for host...',
waitingRoomDescription:
"The meeting hasn't started yet.<br />You'll join automatically when the host opens the room.",
waitingRoomStatus: 'Checking room status...',
waitingRoomReady: 'Room is ready! Joining...',
waitingRoomWaiting: 'Waiting for host to start the meeting...',
waitingRoomHostLink: 'Are you the host?',
waitingRoomLoginLink: 'Login here',
},
html: {
topSponsors: true,
features: true,
browsers: true,
teams: true, // please keep me always true ;)
tryEasier: true,
poweredBy: true,
sponsors: true,
advertisers: true,
supportUs: true,
footer: true,
},
about: {
imageUrl: '../images/mirotalk-logo.gif',
title: 'WebRTC P2P v1.7.50',
html: `
<button
id="support-button"
data-umami-event="Support button"
onclick="window.open('https://codecanyon.net/user/miroslavpejic85')">
<i class="fas fa-heart" ></i>&nbsp;Support
</button>
<br /><br /><br />
Author:<a
id="linkedin-button"
data-umami-event="Linkedin button"
href="https://www.linkedin.com/in/miroslav-pejic-976a07101/" target="_blank">
Miroslav Pejic
</a>
<br /><br />
Email:<a
id="email-button"
data-umami-event="Email button"
href="mailto:miroslav.pejic.85@gmail.com?subject=MiroTalk P2P info">
miroslav.pejic.85@gmail.com
</a>
<br /><br />
<hr />
<span>&copy; 2025 MiroTalk P2P, all rights reserved</span>
<hr />
`,
},
widget: {
enabled: false,
roomId: 'support-room',
theme: 'dark',
widgetState: 'minimized',
widgetType: 'support',
supportWidget: {
position: 'top-right',
expertImages: [
'https://photo.cloudron.pocketsolution.net/uploads/original/95/7d/a5f7f7a2c89a5fee7affda5f013c.jpeg',
],
buttons: {
audio: true,
video: true,
screen: true,
chat: true,
join: true,
},
checkOnlineStatus: false,
isOnline: true,
customMessages: {
heading: 'Need Help?',
subheading: 'Get instant support from our expert team!',
connectText: 'connect in < 5 seconds',
onlineText: 'We are online',
offlineText: 'We are offline',
poweredBy: 'Powered by MiroTalk',
},
},
},
//...
};
/**
* Get started
*/
async function initBrand() {
await getBrand();
handleBrand();
handleWidget();
}
/**
* Get brand from server
*/
async function getBrand() {
if (brandData) {
setBrand(JSON.parse(brandData));
} else {
try {
const response = await fetch('/brand', { timeout: 5000 });
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
const serverBrand = data.message;
if (serverBrand) {
setBrand(serverBrand);
console.log('FETCH BRAND SETTINGS', {
serverBrand: serverBrand,
clientBrand: brand,
});
window.sessionStorage.setItem(brandDataKey, JSON.stringify(serverBrand));
} else {
console.warn('FETCH BRAND SETTINGS - DISABLED');
}
} catch (error) {
console.error('FETCH GET BRAND ERROR', error.message);
}
}
}
/**
* Set brand
* @param {object} data
*/
function setBrand(data) {
brand = mergeBrand(brand, data);
console.log('Set Brand done');
}
/**
* Deep merge two objects
* @param {object} target target object
* @param {object} source source object
* @returns {object} merged object
*/
function mergeBrand(target, source) {
if (typeof target !== 'object' || target === null) return source;
if (typeof source !== 'object' || source === null) return source;
const output = Array.isArray(target) ? target.slice() : { ...target };
for (const key of Object.keys(source)) {
const srcVal = source[key];
const tgtVal = output[key];
if (srcVal && typeof srcVal === 'object' && !Array.isArray(srcVal)) {
output[key] = mergeBrand(tgtVal || {}, srcVal);
} else {
output[key] = srcVal;
}
}
return output;
}
/**
* Handle Brand
*/
function handleBrand() {
if (landingTitle && brand.site?.landingTitle) landingTitle.textContent = brand.site.landingTitle;
if (newCallTitle && brand.site?.newCallTitle) newCallTitle.textContent = brand.site.newCallTitle;
if (newCallRoomTitle && brand.site?.newCallRoomTitle) newCallRoomTitle.innerHTML = brand.site.newCallRoomTitle;
if (newCallRoomDescription && brand.site?.newCallRoomDescription)
newCallRoomDescription.textContent = brand.site.newCallRoomDescription;
if (loginTitle && brand.site?.loginTitle) loginTitle.textContent = brand.site.loginTitle;
if (loginHeading && brand.site?.loginHeading) loginHeading.textContent = brand.site.loginHeading;
if (loginDescription && brand.site?.loginDescription) loginDescription.textContent = brand.site.loginDescription;
if (loginButtonLabel && brand.site?.loginButtonLabel) loginButtonLabel.textContent = brand.site.loginButtonLabel;
if (joinRoomTitle && brand.site?.joinRoomTitle) joinRoomTitle.innerHTML = brand.site.joinRoomTitle;
if (joinRoomButtonLabel && brand.site?.joinRoomButtonLabel)
joinRoomButtonLabel.textContent = brand.site.joinRoomButtonLabel;
if (privacyPolicyTitle && brand.site?.privacyPolicyTitle)
privacyPolicyTitle.textContent = brand.site.privacyPolicyTitle;
if (stunTurnTitle && brand.site?.stunTurnTitle) stunTurnTitle.textContent = brand.site.stunTurnTitle;
if (clientTitle && brand.site?.clientTitle) clientTitle.textContent = brand.site.clientTitle;
if (notFoundTitle && brand.site?.notFoundTitle) notFoundTitle.textContent = brand.site.notFoundTitle;
if (waitingRoomTitle && brand.site?.waitingRoomTitle) waitingRoomTitle.textContent = brand.site.waitingRoomTitle;
if (waitingRoomHeading && brand.site?.waitingRoomHeading)
waitingRoomHeading.textContent = brand.site.waitingRoomHeading;
if (waitingRoomDescription && brand.site?.waitingRoomDescription)
waitingRoomDescription.innerHTML = brand.site.waitingRoomDescription;
if (waitingRoomStatus && brand.site?.waitingRoomStatus)
waitingRoomStatus.textContent = brand.site.waitingRoomStatus;
if (waitingRoomHostLink && brand.site?.waitingRoomHostLink)
waitingRoomHostLink.textContent = brand.site.waitingRoomHostLink;
if (waitingRoomLoginLink && brand.site?.waitingRoomLoginLink)
waitingRoomLoginLink.textContent = brand.site.waitingRoomLoginLink;
if (shortcutIcon && brand.site?.shortcutIcon) shortcutIcon.href = brand.site.shortcutIcon;
if (appleTouchIcon && brand.site?.appleTouchIcon) appleTouchIcon.href = brand.site.appleTouchIcon;
if (appTitle && brand.app?.title) appTitle.innerHTML = brand.app.title;
if (appDescription && brand.app?.description) appDescription.textContent = brand.app.description;
if (appJoinDescription && brand.app?.joinDescription) appJoinDescription.innerHTML = brand.app.joinDescription;
if (joinRoomBtn && brand.app?.joinButtonLabel) joinRoomBtn.innerText = brand.app.joinButtonLabel;
if (customizeRoomBtn && brand.app?.customizeRoomButtonLabel)
customizeRoomBtn.innerText = brand.app.customizeRoomButtonLabel;
if (appJoinLastRoom && brand.app?.joinLastLabel) appJoinLastRoom.innerText = brand.app.joinLastLabel;
// helper to toggle multiple elements
const displayElements = (list) => list.forEach(([el, show]) => elementDisplay(el, !!show));
displayElements([
[topSponsors, brand.html?.topSponsors],
[features, brand.html?.features],
[browsers, brand.html?.browsers],
[teams, brand.html?.teams],
[tryEasier, brand.html?.tryEasier],
[poweredBy, brand.html?.poweredBy],
[sponsors, brand.html?.sponsors],
[advertisers, brand.html?.advertisers],
[supportUs, brand.html?.supportUs],
[footer, brand.html?.footer],
]);
}
// WIDGET customize
function handleWidget() {
if (brand.widget?.enabled) {
const domain = window.location.host;
const roomId = brand.widget?.roomId || 'support-room';
const userName = 'guest-' + Math.floor(Math.random() * 10000);
if (typeof MiroTalkWidget !== 'undefined') {
new MiroTalkWidget(domain, roomId, userName, brand.widget);
} else {
console.warn('MiroTalkWidget is not defined. Please check widget.js loading.', {
domain,
roomId,
userName,
widget: brand.widget,
});
}
}
}
/**
* Handle Element display
* @param {object} element
* @param {boolean} display
* @param {string} mode
*/
function elementDisplay(element, display, mode = 'block') {
if (!element) return;
element.style.display = display ? mode : 'none';
}
initBrand();