Files
pamietnik/backend/static-ts/autoplay.ts
Christoph K. 17186e7b64
All checks were successful
Deploy to NAS / deploy (push) Successful in 2m20s
Add TypeScript migration, image resizing, media upload UX, and multimedia support
- Migrate static JS to TypeScript (static-ts/ → compiled to internal/api/static/)
- Add image resizing on upload: JPEG/PNG/WebP scaled to max 1920px at quality 80
- Extract shared upload logic into upload.go (saveUpload, saveResizedImage, saveResizedWebP)
- Add POST /media endpoint for drag-drop/paste media uploads with markdown ref return
- Add background music player with video/audio coordination (autoplay.ts)
- Add global nav, public feed, hashtags, visibility, Markdown rendering for entries
- Add Dockerfile stage for TypeScript compilation (static-ts-builder)
- Add goldmark, disintegration/imaging, golang.org/x/image dependencies

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 23:03:04 +02:00

96 lines
3.4 KiB
TypeScript

(function () {
'use strict';
/* ── Background player ───────────────────────────────────── */
const bgAudio = new Audio();
let bgPlaying = false;
let bgBar: HTMLElement | null = null;
let bgTitle: HTMLElement | null = null;
let bgPlayBtn: HTMLButtonElement | null = null;
function createBgBar(): void {
if (bgBar) return;
bgBar = document.createElement('div');
bgBar.id = 'bg-bar';
bgBar.innerHTML =
'<span id="bg-title"></span>' +
'<button id="bg-play" aria-label="Abspielen">▶</button>' +
'<button id="bg-close" aria-label="Schließen">✕</button>';
document.body.appendChild(bgBar);
bgTitle = document.getElementById('bg-title');
bgPlayBtn = document.getElementById('bg-play') as HTMLButtonElement;
bgPlayBtn.addEventListener('click', function () {
if (bgAudio.paused) void bgAudio.play(); else bgAudio.pause();
});
document.getElementById('bg-close')?.addEventListener('click', function () {
bgAudio.pause();
if (bgBar) bgBar.style.display = 'none';
});
bgAudio.addEventListener('play', function () { if (bgPlayBtn) bgPlayBtn.textContent = '⏸'; });
bgAudio.addEventListener('pause', function () { if (bgPlayBtn) bgPlayBtn.textContent = '▶'; });
bgAudio.addEventListener('ended', function () { if (bgPlayBtn) bgPlayBtn.textContent = '▶'; });
}
function sendToBg(src: string, title: string): void {
createBgBar();
if (bgBar) bgBar.style.display = 'flex';
bgAudio.src = src;
if (bgTitle) bgTitle.textContent = title;
void bgAudio.play();
}
// Attach "♪" button to every inline audio player
document.querySelectorAll<HTMLAudioElement>('audio.media-audio').forEach(function (a) {
const btn = document.createElement('button');
btn.className = 'btn-bg-music';
btn.textContent = '♪ Hintergrundmusik';
btn.type = 'button';
const title = a.title || a.src.split('/').pop() || a.src;
btn.addEventListener('click', function () { sendToBg(a.src, title); });
a.insertAdjacentElement('afterend', btn);
});
/* ── Video autoplay + coordination ──────────────────────── */
const obs = new IntersectionObserver(function (entries: IntersectionObserverEntry[]) {
entries.forEach(function (e) {
const v = e.target as HTMLVideoElement;
if (e.isIntersecting) {
void v.play();
} else {
v.pause();
}
});
}, { threshold: 0.3 });
document.querySelectorAll<HTMLVideoElement>('video.media-embed').forEach(function (v) {
v.muted = true;
v.loop = true;
v.setAttribute('playsinline', '');
obs.observe(v);
// User unmutes → pause background music
v.addEventListener('volumechange', function () {
if (!v.muted && !v.paused) {
bgPlaying = !bgAudio.paused;
bgAudio.pause();
}
// Video muted again → resume background
if (v.muted && bgPlaying) {
void bgAudio.play();
bgPlaying = false;
}
});
// Video pauses or ends → resume background if it was playing
v.addEventListener('pause', function () {
if (bgPlaying) { void bgAudio.play(); bgPlaying = false; }
});
v.addEventListener('ended', function () {
if (bgPlaying) { void bgAudio.play(); bgPlaying = false; }
});
});
})();