Camera sharing, and the proxy's relay for the desktop app

- A camera is a second source in the share dialog; streams carry their kind,
  so icons and wording follow. Browsers without screen capture (phones) start
  on the camera.
- Settings, Voice: the address of a mumh5 web version as relay; its STUN and
  relay are then offered with every stream and take over when no direct
  connection comes up.
- The proxy hands out relay credentials at GET /api/relay, readable from any
  origin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-01 23:52:18 +02:00
co-authored by Claude Opus 5.5
parent 08aa5268d0
commit 819db06bc6
19 changed files with 208 additions and 78 deletions
+4 -3
View File
@@ -169,14 +169,15 @@
<span class="label" class:talking={voice.talking[u.session] || (isSelf && voice.transmitting)}>{store.displayName(u)}</span>
{#if u.userId != null}<span class="reg" title="Registered">R</span>{/if}
{#if session.sharing[u.session]}
{@const kind = session.sharing[u.session]}
{#if isSelf}
<span class="state sharing" title="You are sharing your screen"><Icon name="screen" size={14} /></span>
<span class="state sharing" title="You are sharing your {kind}"><Icon name={kind} size={14} /></span>
{:else}
<!-- A button cannot sit inside the row's button -->
<span class="state sharing" role="button" tabindex="0" title="Sharing their screen. Click to watch" aria-label="Watch the screen of {store.displayName(u)}"
<span class="state sharing" role="button" tabindex="0" title="Sharing their {kind}. Click to watch" aria-label="Watch the {kind} of {store.displayName(u)}"
onclick={e => { e.stopPropagation(); clearTimeout(timer); share.watch(sessions.active, u.session); }}
ondblclick={e => e.stopPropagation()}
onkeydown={e => { if (e.key === 'Enter') { e.stopPropagation(); share.watch(sessions.active, u.session); } }}><Icon name="screen" size={14} /></span>
onkeydown={e => { if (e.key === 'Enter') { e.stopPropagation(); share.watch(sessions.active, u.session); } }}><Icon name={kind} size={14} /></span>
{/if}
{/if}
{#if u.comment || u.commentHash}<span class="state" title="Has a description"><Icon name="message" size={12} /></span>{/if}