guestlink v1: self-hosted guest line (Cleanfeed replacement)
Go + Pion + libopus. One guest, live audio both ways, anonymous chat. README for this version was not preserved; see the next commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
b0e3b805b1
13 files changed
+1839
No files matched your search
@@ -0,0 +1,30 @@
|
||||
'use strict';
|
||||
const $ = s => document.querySelector(s);
|
||||
function wsURL(path){ return (location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host + path; }
|
||||
function fmtTime(ts){ const d = new Date(ts); return d.toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'}); }
|
||||
// Render a chat message. `mine` = which side this page is ('host' | 'guest'). Text only - never innerHTML.
|
||||
function renderMsg(log, m, mine){
|
||||
const el = document.createElement('div');
|
||||
el.className = 'msg ' + (m.who === 'system' ? 'system' : (m.who === mine ? 'me' : 'them'));
|
||||
if (m.who !== 'system') {
|
||||
const w = document.createElement('span'); w.className = 'who';
|
||||
w.textContent = (m.who === mine ? 'You' : m.from) + ' · ' + fmtTime(m.ts);
|
||||
el.appendChild(w);
|
||||
}
|
||||
el.appendChild(document.createTextNode(m.text));
|
||||
const atBottom = log.scrollHeight - log.scrollTop - log.clientHeight < 40;
|
||||
log.appendChild(el);
|
||||
if (atBottom || m.who === mine) log.scrollTop = log.scrollHeight;
|
||||
}
|
||||
function setMeter(el, peak){ // peak 0..1 linear -> bar on a -60..0 dBFS scale
|
||||
const db = peak > 0 ? 20*Math.log10(peak) : -100;
|
||||
const pct = Math.max(0, Math.min(100, (db + 60) / 60 * 100));
|
||||
el.style.width = pct + '%';
|
||||
el.className = db > -1 ? 'clip' : (db > -9 ? 'hot' : '');
|
||||
return db;
|
||||
}
|
||||
function chatForm(form, ta, send){
|
||||
form.addEventListener('submit', e => { e.preventDefault(); const t = ta.value.trim(); if (t) { send(t); ta.value=''; } ta.focus(); });
|
||||
ta.addEventListener('keydown', e => { if (e.key === 'Enter' && !e.shiftKey && !e.isComposing) { e.preventDefault(); form.requestSubmit(); } });
|
||||
}
|
||||
function store(k, v){ try { if (v === undefined) return localStorage.getItem(k); localStorage.setItem(k, v); } catch(e) { return null; } }
|
||||
Reference in new issue
Block a user