|
|
|
@@ -36,69 +36,26 @@ async function loadTracks() {
|
|
|
|
|
|
|
|
|
|
let webamp = null;
|
|
|
|
|
|
|
|
|
|
// Load the UMD bundle as a classic script. Hide any AMD/CommonJS globals on the page
|
|
|
|
|
// while it runs, so the bundle always attaches itself to window.Webamp.
|
|
|
|
|
function loadWebamp() {
|
|
|
|
|
if (window.Webamp) return Promise.resolve(window.Webamp);
|
|
|
|
|
return new Promise((ok, fail) => {
|
|
|
|
|
const saved = { define: window.define, module: window.module, exports: window.exports };
|
|
|
|
|
window.define = window.module = window.exports = undefined;
|
|
|
|
|
const restore = () => Object.assign(window, saved);
|
|
|
|
|
const s = document.createElement('script');
|
|
|
|
|
s.src = new URL('webamp.bundle.min.js', import.meta.url).href;
|
|
|
|
|
s.onload = () => {
|
|
|
|
|
restore();
|
|
|
|
|
window.Webamp ? ok(window.Webamp) : fail(new Error('Webamp global missing after load'));
|
|
|
|
|
};
|
|
|
|
|
s.onerror = () => { restore(); fail(new Error('could not load ' + s.src)); };
|
|
|
|
|
document.head.appendChild(s);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function open() {
|
|
|
|
|
if (webamp) {
|
|
|
|
|
// Already open (maybe off-screen or hidden): close and reopen so it lands centered in view.
|
|
|
|
|
if (webamp) return;
|
|
|
|
|
const { default: Webamp } = await import('https://unpkg.com/webamp@1.5.0/built/webamp.bundle.min.mjs');
|
|
|
|
|
if (!Webamp.browserIsSupported()) return;
|
|
|
|
|
webamp = new Webamp({ initialTracks: await loadTracks() });
|
|
|
|
|
webamp.onClose(() => {
|
|
|
|
|
webamp.dispose();
|
|
|
|
|
webamp = null;
|
|
|
|
|
document.getElementById('teahub-webamp')?.remove();
|
|
|
|
|
}
|
|
|
|
|
btn.textContent = '… webamp';
|
|
|
|
|
try {
|
|
|
|
|
const Webamp = await loadWebamp();
|
|
|
|
|
if (!Webamp.browserIsSupported()) throw new Error('browser not supported');
|
|
|
|
|
webamp = new Webamp({ initialTracks: await loadTracks() });
|
|
|
|
|
webamp.onClose(() => {
|
|
|
|
|
webamp.dispose();
|
|
|
|
|
webamp = null;
|
|
|
|
|
try { localStorage.removeItem(KEY); } catch {}
|
|
|
|
|
});
|
|
|
|
|
const host = document.createElement('div');
|
|
|
|
|
host.id = 'teahub-webamp';
|
|
|
|
|
// Webamp centers itself in this node, so make it exactly the visible viewport.
|
|
|
|
|
host.style.cssText = 'position:fixed;left:0;top:0;width:100vw;height:100vh;pointer-events:none';
|
|
|
|
|
document.body.appendChild(host);
|
|
|
|
|
await webamp.renderWhenReady(host);
|
|
|
|
|
try { localStorage.setItem(KEY, '1'); } catch {}
|
|
|
|
|
btn.textContent = '▶ webamp';
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error('[teahub webamp]', err);
|
|
|
|
|
webamp = null;
|
|
|
|
|
btn.textContent = '✕ webamp';
|
|
|
|
|
btn.title = String(err && err.message || err);
|
|
|
|
|
}
|
|
|
|
|
try { localStorage.removeItem(KEY); } catch {}
|
|
|
|
|
});
|
|
|
|
|
await webamp.renderWhenReady(document.body.appendChild(document.createElement('div')));
|
|
|
|
|
try { localStorage.setItem(KEY, '1'); } catch {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Keep Webamp pinned to the viewport and above Gitea's own layers.
|
|
|
|
|
const style = document.createElement('style');
|
|
|
|
|
style.textContent = '#webamp{position:fixed!important;z-index:99990!important}';
|
|
|
|
|
document.head.appendChild(style);
|
|
|
|
|
|
|
|
|
|
// Small launcher in the corner: the "sound system" button.
|
|
|
|
|
const btn = document.createElement('button');
|
|
|
|
|
btn.textContent = '▶ webamp';
|
|
|
|
|
btn.title = 'Open Webamp';
|
|
|
|
|
btn.style.cssText = [
|
|
|
|
|
'position:fixed', 'right:12px', 'bottom:12px', 'z-index:99999',
|
|
|
|
|
'position:fixed', 'right:12px', 'bottom:12px', 'z-index:9999',
|
|
|
|
|
'font:12px/1 monospace', 'padding:6px 10px', 'border-radius:4px',
|
|
|
|
|
'border:1px solid #1d3', 'background:#000', 'color:#1d3', 'cursor:pointer',
|
|
|
|
|
].join(';');
|
|
|
|
|