Commit graph

86 commits

Author SHA1 Message Date
Daniel
1bcfef68fe Navbar: Nur Plugins mit Frontend-Component als Tab anzeigen
Filtert Backend-only Plugins (z.B. Notifications) aus der Tab-Leiste.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 20:11:19 +01:00
Daniel
1cf79ef917 Notification-Bot: Discord-Benachrichtigungen für Streams
- Neues Notification-Plugin mit eigenem Discord-Bot
- Admin-Modal im Streaming-Tab für Channel-Konfiguration
- Automatische Benachrichtigungen bei Stream-Start/Ende
- Stream-Links mit Passwort-Hinweis in Discord-Embeds
- Konfigurierbare Events pro Channel (stream_start, stream_end)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 19:29:52 +01:00
Daniel
2c570febd1 Soundboard: Drag & Drop mit Rename-Modal
- MP3/WAV per Drag & Drop ablegen öffnet jetzt ein Rename-Modal
- Jede Datei einzeln benennen vor dem Upload (sequentiell bei mehreren)
- Server-Upload-Endpoint unterstützt optionalen customName Parameter
- Reuse der bestehenden dl-modal CSS-Klassen für konsistentes Design
- Überspringen-Option bei mehreren Dateien

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 19:11:23 +01:00
Daniel
59428a2c65 Steam-Button nur in Übersicht anzeigen, nicht im Profil-Detail
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 19:00:36 +01:00
Daniel
962ea9ebfc GOG-Button nur im Profil-Detail anzeigen
GOG kann nur innerhalb eines bestehenden Profils verknuepft werden,
damit der Account dem richtigen Spieler zugeordnet wird.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:53:54 +01:00
Daniel
71b35d573e Game Library: Admin-Panel, Disconnect-UI, IGDB-Cache
- Admin-Panel mit Login (gleiches Passwort wie Soundboard) zum Entfernen
  von Profilen inkl. aller verknuepften Daten
- Disconnect-Buttons im Profil-Detail: Steam/GOG einzeln trennbar
- IGDB persistenter File-Cache (ueberlebt Server-Neustarts)
- SSE-Broadcast-Format korrigiert (buildProfileSummaries shared helper)
- DELETE-Endpoints fuer Profil/Steam/GOG Trennung

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:53:10 +01:00
Daniel
d909909591 Auto-Updater: Doppelstart verhindern + Download-Status sichtbar
- State-Tracking im Main-Prozess (idle/checking/downloading/ready)
- Manueller Check gibt aktuellen Status zurück statt Squirrel-Doppelstart
- Auto-Check nur wenn idle (kein Konflikt mit laufendem Download)
- Frontend synchronisiert Status beim Mount und Modal-Öffnen
- getUpdateStatus IPC für synchrone Status-Abfrage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:27:35 +01:00
Daniel
3e8febb851 GOG Login: Nahtloser Auth-Flow wie Steam (kein Code-Paste noetig)
- Electron: Fängt GOG Redirect automatisch ab (will-redirect Interceptor)
- Code-Exchange passiert im Hintergrund, User sieht nur Erfolgs-Popup
- GOG Auth-URLs (auth.gog.com, login.gog.com, embed.gog.com) in Popup erlaubt
- Server: GET /gog/login Redirect + POST /gog/exchange Endpoint
- Browser-Fallback: Code-Paste Dialog falls nicht in Electron
- gog.ts: Feste redirect_uri (embed.gog.com/on_login_success)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 14:41:21 +01:00
Daniel
ee5c29dd7b Game Library: Multi-Platform Profile System + GOG Integration
- Neues Profile-System: User können Steam und GOG verknüpfen
- GOG OAuth2 Login-Flow (auth.gog.com)
- GOG API Service (gog.ts): Token-Management, Spieleliste, User-Info
- Server: Profile-Datenmodell, Migration bestehender Steam-Users
- Frontend: Login-Bar (Steam + GOG), Profile-Chips mit Platform-Badges
- Cross-Platform Game-Merging mit Deduplizierung
- Profile-Detail mit "GOG verknüpfen" Option

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 12:34:43 +01:00
Daniel
f64aac707a Game Library: Genre-Filter + Sortierung (Spielzeit/Bewertung/Name)
- Genre-Chips als Filter-Bar in User- und Common-Games-Ansicht
- Sortierung umschaltbar: Spielzeit, Bewertung, Name
- Multi-Genre-Auswahl mit "Alle"-Reset
- Common Games zeigen jetzt auch Genres und Ratings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 10:42:21 +01:00
Daniel
d6973c811c Entferne Plattform-Badges aus Game Library
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 02:01:46 +01:00
Daniel
4994d5c245 IGDB auto-enrichment: Server-Start + Frontend auto-trigger
- Server enriched bestehende User beim Plugin-Start automatisch (fire-and-forget)
- Frontend triggert IGDB-Enrichment automatisch beim Öffnen einer User-Bibliothek
- Reduzierte Log-Ausgabe (kein Spam pro Cache-Hit mehr)
- IGDB-Button zeigt Lade-Animation während Enrichment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 01:58:11 +01:00
Daniel
b404c20eca IGDB-Integration für Game Library + Electron Update-Button im Version-Modal
- Neues IGDB-Service-Modul (igdb.ts): Token-Management, Rate-Limiting, Game-Lookup per Steam-AppID/Name, Batch-Enrichment mit In-Memory-Cache
- Server: 2 neue Routes (/igdb/enrich/:steamId, /igdb/game/:appid), Auto-Enrichment bei Steam-Login und Refresh
- Frontend: IGDB-Cover, Genre-Tags, Plattform-Badges, farbcodiertes Rating, IGDB-Anreichern-Button
- Version-Modal: Update-Button für Electron-App (checkForUpdates/installUpdate), Desktop-App-Version anzeigen
- CSS: Styles für IGDB-Elemente und Update-UI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 01:48:27 +01:00
Daniel
e146a28416 Streaming: Bildschirmauswahl-Picker, Passwort optional, Windows-Toast-Notifications
- Electron: setDisplayMediaRequestHandler zeigt jetzt immer einen modalen Picker
  mit Thumbnails statt automatisch die letzte Quelle zu verwenden
- Passwort bei Streams ist jetzt optional (Server + Frontend)
- Streams ohne Passwort: direkter Beitritt ohne Modal
- hasPassword wird korrekt im stream_available Event übertragen
- Windows Toast-Notifications via Electron Notification API für
  "Stream gestartet" und "Neuer Stream" Events
- Browser-Variante nutzt weiterhin Web Notification API

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 00:16:48 +01:00
Daniel
dec6be5476 Fix: Seek funktioniert jetzt für alle User — report_time überschreibt Seek nicht mehr
- Server: report_time ignoriert Host-Updates für 2s nach einem Seek
- Frontend: seekingRef Guard auf 3s erhöht um Sync-Pulse-Rücksetzung zu verhindern

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:56:04 +01:00
Daniel
253a249fc7 Watch Together: alle User haben Stream-Kontrolle, Dailymotion-Support, YouTube-Qualitätswahl
- Host-Only-Beschränkung für play/pause/resume/seek/skip entfernt — alle Raum-Mitglieder können jetzt die Wiedergabe steuern
- Dailymotion-Videos können jetzt abgespielt werden (postMessage API, iframe-basiert)
- YouTube-Videoqualität einstellbar (Standard: 1080p, wird in localStorage gespeichert)
- Queue-Items sind für alle User klickbar
- "Gesehene entfernen"-Button für alle sichtbar

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:49:31 +01:00
Daniel
87b4467995 Feature: Game Library Plugin - Steam Spielebibliothek
- Neues Plugin: game-library mit Steam OpenID 2.0 Login
- Steam GetOwnedGames API zum Abrufen der Spielebibliothek
- Gemeinsame Spiele finden (Schnittmenge mehrerer Bibliotheken)
- Spielesuche ueber alle verbundenen User
- User-Profil mit Spielzeit-Sortierung
- JSON-basierte Persistenz in /data/game-library.json
- Steam API Key als CI/CD Variable konfiguriert
- Frontend: User Cards, Common Games Finder, Suchfunktion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:31:40 +01:00
Daniel
33e718ddf6 Remove: Electron Desktop-App Versionsnummer und Update-Check
Desktop App ist nur ein Wrapper - Web-Inhalte updaten sich automatisch.
Separate Version verwirrt User wenn sie nicht übereinstimmt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 22:44:00 +01:00
Daniel
8aefb49ff3 Feature: Watch Together - Chat, Voting, Sync-Indicator, Join-per-Link
- Raumliste zeigt jetzt Teilnehmernamen
- Join per Link (?wt=roomId) für einfaches Teilen
- Sync-Indikator (grün/gelb/rot) zeigt Synchronstatus
- Pause/Skip-Voting für Nicht-Host-Teilnehmer
- In-Room Chat mit Nachrichtenverlauf
- "Gesehene entfernen" Button für Host in der Queue
- REST endpoint GET /api/watch-together/room/:id

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 22:38:56 +01:00
Daniel
963bb1b775 Watch Together: Videos bleiben in Queue mit Watched-Haken
Statt Videos nach dem Abspielen aus der Warteschlange zu entfernen,
bleiben sie drin und werden mit einem gruenen Haken markiert.
Separate History-Section entfernt — die Queue IST die History.
Videos bleiben klickbar zum erneuten Abspielen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 22:23:45 +01:00
Daniel
0ef2a2899a Electron CI Build + Version Info Modal
CI Pipeline:
- New electron-build stage (electronuserland/builder:wine) builds Windows installer
- New electron-deploy stage copies artifacts to container /data/downloads/
- Triggers on electron/ or VERSION changes + manual trigger
- bump-version now syncs electron/package.json via jq

Version Modal:
- Click version badge to open info modal
- Shows Hub Version, Desktop App Version, Server status
- Hint when versions differ (update available)
- Download link when not using Electron app
- Escape + overlay click to close

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:38:37 +01:00
Daniel
9fd0992fc4 Fix Electron update: Squirrel feed URL, version display, error details
- Fix: Squirrel.Windows feed URL /updates → /downloads (Squirrel appends /RELEASES)
- Show Desktop App + Server version in update modal
- Display actual error message in failed state
- Dynamic Electron version via app.getVersion() instead of hardcoded
- Sync electron/package.json version with VERSION file (1.5.8)
- Add "Später" button on update-ready, timeout error message
- Style: version info, error detail box, secondary button

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:23:30 +01:00
Daniel
6c57419959 Feature: Watch Together - History, Titel-Fetch, Next-Button
Server:
- Video-History Tracking (max 50 Einträge pro Raum)
- History wird bei Skip und Play-Video gespeichert
- Server-seitiger Titel-Fetch via noembed.com als Fallback

Client:
- Aufklappbare History-Sektion im Queue-Panel
- "Weiter" Button mit Text-Label statt nur Icon
- YouTube-Thumbnails in der Warteschlange
- History in RoomState integriert

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 15:31:57 +01:00
Daniel
3455e20a96 Feature: Live Stream-Liste + Toast Notifications
- stream_available/stream_ended WS-Events verarbeiten
- WS sofort beim Mount verbinden (nicht nur beim Broadcasting)
- WS reconnect immer aktiv (nicht nur bei aktivem Stream)
- Toast Notifications: neuer Stream, Update verfügbar/bereit
- Notification Permission beim App-Start anfragen

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 15:05:42 +01:00
Daniel
fa4b379a90 Fix: Stream in gleichem Fenster öffnen + Update-Dialog Abbrechen-Button
- Stream-Tile Klick öffnet Join-Modal statt neues Fenster
- checkForUpdates optional chaining für alte Electron App
- Abbrechen-Button im Update-Check Dialog
- 15s Timeout falls Electron nicht antwortet

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 14:57:41 +01:00
Daniel
e057a61c55 Fix: optional chaining für setStreaming (alte Electron App Kompatibilität)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 14:47:43 +01:00
Daniel
ce2a26ddeb Add: Check-for-Updates Button in Electron App
- Manueller Update-Check per Button im Header
- Modal-Zustaende: checking, downloading, ready, uptodate, error
- IPC: check-for-updates, update-not-available Events
2026-03-07 14:27:09 +01:00
Daniel
c2942737bd Add: Update-Modal mit Download-Fortschritt in Electron App
- Modal-Overlay statt Banner fuer Update-Benachrichtigung
- 3 Zustaende: Downloading (Ladeanimation), Ready (OK-Button), Error
- IPC-Events: update-available, update-ready, update-error
2026-03-07 14:24:59 +01:00
Daniel
9689af4d3a Add: Automatische Versionierung via VERSION-Datei
- VERSION-Datei als Single Source of Truth (startet bei 1.5.1)
- CI liest Version aus Datei statt hardcoded
- Patch-Version wird nach Deploy automatisch gebumpt
- Commit mit [skip ci] verhindert Endlosschleife
2026-03-07 14:17:27 +01:00
Daniel
7bebb7db9a Fix: Stream-close-warning via IPC statt async executeJavaScript
- Renderer meldet Streaming-Status synchron per IPC
- main.js prueft Status synchron im close-Handler
- Kein async Race mehr, Dialog erscheint zuverlaessig
2026-03-07 14:14:51 +01:00
Daniel
7ef4eefc55 Add: Update-Dialog fuer Electron Auto-Updater
- main.js: IPC-Events an Renderer senden wenn Update bereit
- main.js: install-update IPC Handler (quitAndInstall)
- App.tsx: Update-Banner "Neues Update verfuegbar!" mit Restart-Button
- styles.css: Update-Bar Styling passend zum Design-System

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:53:26 +01:00
Daniel
17dcd6073f V1.5.0: Version bump + Download-Button Redesign
- Version auf 1.5.0 in allen Packages, CI, Dockerfile, Electron
- Download-Button im gleichen Design wie Version-Badge (bg-secondary, radius, hover accent)
- CI Registry auf adriahub (192.168.1.100:9080) umgestellt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:38:51 +01:00
Daniel
09813b626f Watch Together: Embed-Fehlerbehandlung, klickbare Queue, Video-Titel
- YouTube onError Handler: Erkennt Error 101/150 (Embedding deaktiviert),
  zeigt Fehlermeldung + "Auf YouTube oeffnen" Link, auto-skip nach 3s
- Queue-Items klickbar fuer Host (play_video mit Index)
- Video-Titel werden via noembed.com oEmbed API geholt
- Server-Endpoint: GET /api/watch-together/video-info?url=...
- "Hinzufuegen" Button zeigt Ladezustand waehrend Titel-Fetch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:19:59 +01:00
Daniel
e4895a792c Fix: WebSocket-Konflikt zwischen Streaming und Watch Together
Root Cause: ws-Library killt WS-Verbindungen mit HTTP 400 wenn
mehrere WebSocketServer mit { server, path } registriert werden.
Der erste WSS (streaming) hat abortHandshake() fuer watch-together
Verbindungen aufgerufen.

- Beide WSS auf noServer-Modus umgestellt
- Zentrales upgrade-Routing in index.ts nach Pathname
- Frontend: connectWs prueft jetzt auch CONNECTING-State
- Frontend: onclose clobbert wsRef nur noch wenn gleicher Socket
- Frontend: waitForWs hat jetzt 10s Timeout statt Endlosschleife

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:02:36 +01:00
Daniel
e748fc97e9 Fix: Watch Together Raum-Erstellung + Download-Button
- Server/Frontend Protokoll-Mismatch behoben (create_room, join_room, room_created, room_joined, playback_state)
- togglePlay sendet jetzt korrekt pause/resume statt toggle_play
- Download-Button: SPA-Fallback fuer /downloads/ verhindert, 404 statt Reload
- download-Attribut am Link hinzugefuegt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 02:48:43 +01:00
Daniel
73f247ada3 Watch Together Plugin + Electron Desktop App mit Ad-Blocker
Neuer Tab: Watch Together - gemeinsam Videos schauen (w2g.tv-Style)
- Raum-System mit optionalem Passwort und Host-Kontrolle
- Video-Queue mit Hinzufuegen/Entfernen/Umordnen
- YouTube (IFrame API) + direkte Video-URLs (.mp4, .webm)
- Synchronisierte Wiedergabe via WebSocket (/ws/watch-together)
- Server-autoritative Playback-State mit Drift-Korrektur (2.5s Sync-Pulse)
- Host-Transfer bei Disconnect, Room-Cleanup nach 30s

Electron Desktop App (electron/):
- Wrapper fuer Gaming Hub mit integriertem Ad-Blocker
- uBlock-Style Request-Filtering via session.webRequest
- 100+ Ad-Domains + YouTube-spezifische Filter
- Download-Button im Web-Header (nur sichtbar wenn nicht in Electron)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 02:40:59 +01:00
Daniel
4943bbf4a1 Streams oeffnen standardmaessig in neuem Fenster mit Passwortabfrage
Klick auf Stream-Tile oeffnet neues Fenster via ?viewStream= URL.
Passwort-Modal erscheint automatisch im neuen Fenster nach dem Laden.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 02:11:16 +01:00
Daniel
59ebfc91a9 Fix: Auto-Join via ?viewStream= URL-Parameter funktioniert jetzt
App.tsx wechselt automatisch zum Streaming-Tab wenn ?viewStream= in der URL steht.
StreamingTab nutzt ref-basierten Ansatz: Stream-ID wird beim Mount gespeichert,
Passwort-Modal oeffnet sich sobald die Stream-Liste vom Server geladen ist.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 02:07:49 +01:00
Daniel
470bef62e4 Streaming: Stale-Stream Fix, Broadcast+View gleichzeitig, 3-Punkt-Menü
Server:
- Dual-Role: Client kann gleichzeitig broadcasten UND zuschauen
  (broadcastStreamId + viewingStreamId statt single role)
- POST /api/streaming/disconnect Beacon-Endpoint fuer
  zuverlaessigen Cleanup bei Page-Unload
- Heartbeat auf 5s reduziert (schnellere Erkennung)

Frontend:
- pagehide + sendBeacon: Streams werden sofort aufgeraeumt wenn
  Browser geschlossen/neugeladen wird
- ICE Routing: Broadcaster-Map wird zuerst geprueft, dann Viewer-PC
  → Broadcast + View im selben Tab moeglich
- 3-Punkt-Menü mit Stream-Details, "In neuem Fenster oeffnen" und
  "Link teilen" (Clipboard)
- Auto-Join via ?viewStream=... Query-Parameter (fuer geteilte Links)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 01:56:14 +01:00
Daniel
813e017036 Fix: Umlaut-Darstellung im Zurueck-Button korrigiert
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 01:45:47 +01:00
Daniel
3ef25fc10a Beforeunload-Warnung + Vollbild-Button fuer Viewer
- beforeunload Event verhindert versehentliches Verlassen/Reload
  waehrend Broadcasting oder Viewing aktiv ist
- Vollbild-Button im Viewer-Header (Fullscreen API)
- Fullscreen-State wird korrekt getrackt und Icon wechselt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 01:37:21 +01:00
Daniel
2ee36789b2 Stream auf 60 FPS + 8 Mbps Bitrate angehoben
- getDisplayMedia: frameRate ideal 60, 1920x1080
- WebRTC Sender: maxFramerate 60, maxBitrate 8 Mbps pro Viewer-PC

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 01:34:55 +01:00
Daniel
3f9b446f27 Fix: Schwarzes Bild bei Viewern - WebRTC Race Conditions behoben
- Doppelter Offer entfernt (onnegotiationneeded + explizit createOffer)
- ICE Candidate Queuing: Candidates werden gepuffert bis setRemoteDescription
  fertig ist, statt sie zu verwerfen
- Cleanup bei Re-Offer: vorherige PeerConnection wird sauber geschlossen
- Pending Candidates werden bei Disconnect/Leave aufgeraeumt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 01:16:09 +01:00
Daniel
c9378f4cdb Fix: Tab-Auswahl bleibt nach Reload erhalten (localStorage)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 01:10:01 +01:00
Daniel
4aed4e70ab fix(streaming): reliable disconnect + mandatory stream password
Disconnect:
- Server-side heartbeat ping/pong every 10s with 25s timeout
- Detects and cleans up dead connections (browser closed, network lost)
- ws.terminate() on heartbeat timeout triggers handleDisconnect

Password:
- Stream password is mandatory (server rejects start_broadcast without)
- Password stored server-side, never sent to clients
- Viewers must enter password via modal before joining
- Lock icon on tiles, WRONG_PASSWORD error shown in modal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 01:00:48 +01:00
Daniel
dacfde4328 fix(streaming): resolve stale closure preventing remote WebRTC connections
The WebSocket onmessage handler captured isBroadcasting=false at creation
time. When ICE candidates arrived from remote viewers, the handler looked
up viewerPcRef instead of peerConnectionsRef, dropping all candidates.

Fix: use refs (isBroadcastingRef, viewingRef, handleWsMessageRef) so the
WS handler always reads current state. connectWs() now has [] deps and
delegates to handleWsMessageRef.current for every message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 00:51:09 +01:00
Daniel
29bcf67121 feat(streaming): add Screen Streaming plugin with WebRTC
New plugin: browser-based screen sharing via Chrome Screen Capture API.
Multi-stream grid layout (Rustdesk-style tiles) with live previews.

- Server: WebSocket signaling at /ws/streaming (SDP/ICE relay)
- Server: http.createServer for WebSocket attachment
- Frontend: StreamingTab with broadcaster/viewer modes
- Frontend: tile grid, fullscreen viewer, LIVE badges
- Supports multiple concurrent streams
- Peer-to-peer video via WebRTC (no video through server)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 00:39:49 +01:00
Daniel
9ff8a38547 feat(soundboard): download modal with filename input + fix yt-dlp binary
- Add download modal: filename input, progress phases (input/downloading/done/error)
- Refactor backend: shared handleUrlDownload() with optional custom filename + rename
- Fix Dockerfile: use yt-dlp_linux standalone binary (no Python dependency)
- Modal shows URL type badge (YouTube/Instagram/MP3), spinner, retry on error

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:59:31 +01:00
Daniel
df937f3e40 fix(soundboard): auto-prepend https:// for URL import
URLs pasted without protocol (e.g. instagram.com/reel/...) now work.
normalizeUrl() adds https:// if missing. Input type changed from
"url" to "text" to prevent browser validation blocking paste.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:45:41 +01:00
Daniel
200f03c1f8 feat(soundboard): extend URL download to support YouTube & Instagram
yt-dlp extracts audio as MP3 from YouTube and Instagram links.
Direct MP3 links continue to work as before. URL input field now shows
a type indicator (YT/IG/MP3) and validates all three formats.

Backend: downloadWithYtDlp() spawns yt-dlp with --extract-audio,
saves to SOUNDS_DIR, normalizes if enabled. New /download-url route
for save-only without auto-play. play-url route extended for all types.

Frontend: isSupportedUrl() validates YouTube/Instagram/MP3, dynamic
icon changes per URL type, disabled state when URL is unsupported.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:38:09 +01:00