AvanzaCast/packages/studio-panel/public/simulate_postmessage.html

155 lines
6.5 KiB
HTML

<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Broadcast to Studio - Simulate (with token fetch)</title>
<style>body{font-family:Arial;margin:20px}button{padding:8px 12px;border-radius:6px}#log{margin-top:12px;color:#111}#status{margin-top:8px;padding:8px;background:#f3f4f6;border-radius:6px}</style>
</head>
<body>
<h3>Broadcast Simulator (token fetch)</h3>
<p>Simula broadcast-panel: solicita token al backend y se lo envía por postMessage a la ventana del estudio.</p>
<label>Token server URL: <input id="tokenServer" type="text" size="40" value="https://avanzacast-servertokens.bfzqqk.easypanel.host" /></label>
<br /><br />
<label>Studio URL: <input id="studioUrl" type="text" size="40" value="https://avanzacast-studio.bfzqqk.easypanel.host" /></label>
<br /><br />
<label>Room: <input id="room" type="text" value="studio-demo" /></label>
<label style="margin-left:12px">Username: <input id="username" type="text" value="simulator" /></label>
<div style="margin-top:12px">
<button id="openSend">Open Studio and Send Token</button>
<button id="openOnly" style="margin-left:8px">Open Studio Only</button>
</div>
<div id="log"></div>
<div id="status" aria-live="polite">Idle</div>
<script>
const btn = document.getElementById('openSend');
const openOnly = document.getElementById('openOnly');
const log = document.getElementById('log');
const status = document.getElementById('status');
function appendLog(msg){
const p = document.createElement('div');
p.textContent = `[${new Date().toISOString()}] ${msg}`;
log.prepend(p);
}
async function fetchToken(tokenServer, room, username, timeoutMs = 6000){
if (!tokenServer) throw new Error('tokenServer empty');
const url = new URL('/api/token', tokenServer).toString() + `?room=${encodeURIComponent(room)}&username=${encodeURIComponent(username)}`;
const controller = new AbortController();
const timer = setTimeout(()=> controller.abort(), timeoutMs);
try{
const resp = await fetch(url, { signal: controller.signal, credentials: 'include' });
clearTimeout(timer);
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
const data = await resp.json();
if (!data || !data.token) throw new Error('Invalid token response');
return { token: data.token, url: data.url || tokenServer };
}catch(err){
clearTimeout(timer);
throw err;
}
}
function fallbackToken(){
// lightweight fake token for local testing
return { token: 'fake-token-' + Math.random().toString(36).slice(2,10), url: 'wss://livekit-server.example' };
}
function sendToStudioWindow(win, payload){
try{
win.postMessage(payload, '*');
appendLog('Sent token to studio popup (postMessage)');
status.textContent = 'Sent token to studio popup';
}catch(e){
appendLog('postMessage failed: ' + e);
status.textContent = 'postMessage failed';
}
}
// New flow: fetch token first, then try to open popup; fallback to redirect if popup blocked
async function doOpenSend(){
const tokenServer = document.getElementById('tokenServer').value.trim();
const studioUrl = document.getElementById('studioUrl').value.trim().replace(/\/$/, '');
const room = document.getElementById('room').value.trim() || 'studio-demo';
const username = document.getElementById('username').value.trim() || 'simulator';
status.textContent = 'Requesting token...';
appendLog('Requesting token from ' + tokenServer + ' for room=' + room + ' username=' + username);
let tokenData;
try{
tokenData = await fetchToken(tokenServer, room, username, 6000);
appendLog('Token obtained from server');
}catch(err){
appendLog('Token request failed: ' + (err && err.message));
appendLog('Using fallback token');
tokenData = fallbackToken();
}
// prepare payload and query params for fallback redirect
const payload = { type: 'LIVEKIT_TOKEN', token: tokenData.token, url: tokenData.url, room };
const q = new URLSearchParams({ token: tokenData.token || '', room: room || '', username: username || '' });
if (tokenData.url) q.set('serverUrl', tokenData.url);
// try open popup to studio_receiver
const receiverUrl = studioUrl + '/studio_receiver.html';
const studioWin = window.open(receiverUrl, 'studio_receiver', 'width=900,height=700');
if (studioWin && !studioWin.closed){
// post the token to the popup
try{
// attempt postMessage multiple times in case the popup is still loading
const tryPost = ()=>{
try{ studioWin.postMessage(payload, '*'); appendLog('postMessage attempted to popup'); }catch(e){ appendLog('postMessage error: '+e); }
}
setTimeout(tryPost, 300);
setTimeout(tryPost, 800);
setTimeout(tryPost, 1500);
status.textContent = 'Token sent to popup (attempted)';
}catch(e){
appendLog('Error sending to popup: ' + e);
// fallback redirect
window.location.href = `${studioUrl}/studio_receiver.html?${q.toString()}`;
}
} else {
appendLog('Popup blocked or not available; redirecting current window to studio with token');
// fallback: redirect current window to studio_receiver with token in querystring
window.location.href = `${studioUrl}/studio_receiver.html?${q.toString()}`;
}
// Listen for ACK from the popup
function onMessage(e){
try{
if (e?.data?.type === 'LIVEKIT_ACK'){
appendLog('ACK from studio: ' + JSON.stringify(e.data));
status.textContent = 'ACK received: ' + (e.data.status || 'ok');
window.removeEventListener('message', onMessage);
}
}catch(err){ /* ignore */ }
}
window.addEventListener('message', onMessage);
}
btn.addEventListener('click', doOpenSend);
openOnly.addEventListener('click', ()=>{
const studioUrl = document.getElementById('studioUrl').value.trim().replace(/\/$/, '');
window.open(studioUrl + '/studio_receiver.html', 'studio_receiver', 'width=900,height=700');
});
// Auto-run if ?auto=1 added to URL
try{
const params = new URLSearchParams(window.location.search);
if (params.get('auto') === '1'){
setTimeout(()=> doOpenSend(), 300);
}
}catch(e){}
</script>
</body>
</html>