window.BackOneRingingPopup = { _audio: null, showIncomingCall({ callerName, callType, callId, onAccept, onReject }) { const el = document.getElementById('ringing-popup'); if (!el) return; el.classList.remove('ringing-hidden'); el.innerHTML = `

Incoming ${callType} call

${callerName || 'Unknown peer'}

`; el.querySelector('.ringing-accept').onclick = () => { this.dismiss(); onAccept && onAccept(callId); }; el.querySelector('.ringing-reject').onclick = () => { this.dismiss(); onReject && onReject(callId); }; this.playRingtone(); if (Notification.permission === 'default') Notification.requestPermission(); if (Notification.permission === 'granted') { new Notification(`Incoming ${callType} call`, { body: callerName || 'BackOne peer' }); } }, dismiss() { const el = document.getElementById('ringing-popup'); if (el) { el.classList.add('ringing-hidden'); el.innerHTML = ''; } this.stopRingtone(); }, playRingtone() { this.stopRingtone(); try { this._audio = new Audio('data:audio/wav;base64,UklGRnoGAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQoGAACBhYqFbF1fdJivrJBhNjVgodDbq2EcBj+a2/LDciUFLIHO8tiJNwgZaLvt559NEAxQp+PwtmMcBjiR1/LMeSwFJHfH8N2QQAoUXrTp66hVFApGn+DyvmwhBSuBzvLZiTYIG2m98OScTgwOUarm7blmHgU7k9n1unEiBC13y+/ek0EKElyx5+ytWBUIQ5zd8sFuJAUwgM/z2Ik6CBxpvfDknE4MDlGq5u25Zh4FO5PZ9br'); this._audio.loop = true; this._audio.play().catch(() => {}); } catch (_) {} }, stopRingtone() { if (this._audio) { this._audio.pause(); this._audio = null; } } }; async function loadAddonManifest() { const res = await fetch('/app/addons/manifest.json', { cache: 'no-store' }); if (!res.ok) { console.warn('manifest.json fetch failed:', res.status); return []; } const data = await res.json(); return Array.isArray(data) ? data : []; } async function loadAddonModule(entry) { const entryPath = entry.frontend && entry.frontend.entry ? entry.frontend.entry : `/app/addons/${entry.id}/index.js`; await import(entryPath); const factory = window.BackOneAddons && window.BackOneAddons[entry.id]; return factory ? factory() : null; } window.BackOneAddonLoader = { loadAddonManifest, loadAddonModule };