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>
This commit is contained in:
Daniel 2026-03-07 01:56:14 +01:00
parent 813e017036
commit 470bef62e4
7 changed files with 5091 additions and 5013 deletions

View file

@ -182,12 +182,15 @@
}
/* Three-dot menu */
.stream-tile-menu-wrap {
position: relative;
}
.stream-tile-menu {
background: none;
border: none;
color: var(--text-muted);
cursor: pointer;
padding: 4px;
padding: 4px 6px;
font-size: 18px;
line-height: 1;
border-radius: 4px;
@ -198,6 +201,59 @@
color: var(--text-normal);
}
/* Dropdown menu */
.stream-tile-dropdown {
position: absolute;
bottom: calc(100% + 6px);
right: 0;
background: var(--bg-secondary);
border: 1px solid var(--bg-tertiary);
border-radius: var(--radius-lg);
min-width: 220px;
z-index: 100;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
overflow: hidden;
}
.stream-tile-dropdown-header {
padding: 12px 14px;
}
.stream-tile-dropdown-name {
font-size: 14px;
font-weight: 600;
color: var(--text-normal);
}
.stream-tile-dropdown-title {
font-size: 12px;
color: var(--text-muted);
margin-top: 2px;
}
.stream-tile-dropdown-detail {
font-size: 11px;
color: var(--text-faint);
margin-top: 6px;
}
.stream-tile-dropdown-divider {
height: 1px;
background: var(--bg-tertiary);
}
.stream-tile-dropdown-item {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
padding: 10px 14px;
border: none;
background: none;
color: var(--text-normal);
font-size: 13px;
cursor: pointer;
text-align: left;
transition: background var(--transition);
}
.stream-tile-dropdown-item:hover {
background: var(--bg-tertiary);
}
/* ── Fullscreen Viewer ── */
.stream-viewer-overlay {
position: fixed;