From 288bcfe5d7efaf1f1cdb9e27127c3d9d974dd61d Mon Sep 17 00:00:00 2001 From: mplorentz Date: Wed, 8 Apr 2026 11:09:52 -0400 Subject: [PATCH] Cleanup remaining files --- src/app/call/stores.ts | 1 - src/app/call/video.ts | 30 +++++------ src/app/call/voice.ts | 4 +- src/app/components/VideoCallContent.svelte | 28 +++++----- ...oCallVideo.svelte => VideoCallTile.svelte} | 14 ++--- .../VoiceCallAudioSettingsDialog.svelte | 13 ++--- src/app/components/VoiceWidget.svelte | 52 +++++++++---------- 7 files changed, 62 insertions(+), 80 deletions(-) rename src/app/components/{VideoCallVideo.svelte => VideoCallTile.svelte} (66%) diff --git a/src/app/call/stores.ts b/src/app/call/stores.ts index 95ccc0b8..abe4084e 100644 --- a/src/app/call/stores.ts +++ b/src/app/call/stores.ts @@ -47,7 +47,6 @@ export const isParticipantSpeaking = derived( $participants.some(sp => participantKey(sp) === participantKey(p)), ) -/** True when the local user is in LiveKit’s active-speakers list (currently talking). */ export const isLocalSpeaking = derived( [currentVoiceSession, speakingParticipants], ([$session, $speaking]) => { diff --git a/src/app/call/video.ts b/src/app/call/video.ts index 3a420005..eccd4397 100644 --- a/src/app/call/video.ts +++ b/src/app/call/video.ts @@ -71,17 +71,14 @@ export const toggleCamera = async () => { if (!session) return const cameraOn = !session.cameraOn - if (!cameraOn) { - session.room.localParticipant.setCameraEnabled(false) - currentVoiceSession.set({...session, cameraOn}) - return - } - try { - await session.room.localParticipant.setCameraEnabled(true) + await session.room.localParticipant.setCameraEnabled(cameraOn) currentVoiceSession.set({...session, cameraOn}) - } catch (e) { - pushToast({theme: "error", message: "Could not access camera"}) + } catch { + pushToast({ + theme: "error", + message: cameraOn ? "Could not access camera" : "Could not turn off camera", + }) } } @@ -90,16 +87,13 @@ export const toggleScreenShare = async () => { if (!session) return const screenShareOn = !session.screenShareOn - if (!screenShareOn) { - session.room.localParticipant.setScreenShareEnabled(false) - currentVoiceSession.set({...session, screenShareOn}) - return - } - try { - await session.room.localParticipant.setScreenShareEnabled(true) + await session.room.localParticipant.setScreenShareEnabled(screenShareOn) currentVoiceSession.set({...session, screenShareOn}) - } catch (e) { - pushToast({theme: "error", message: "Could not start screen sharing"}) + } catch { + pushToast({ + theme: "error", + message: screenShareOn ? "Could not start screen sharing" : "Could not stop screen sharing", + }) } } diff --git a/src/app/call/voice.ts b/src/app/call/voice.ts index 33449ebc..95cab6a5 100644 --- a/src/app/call/voice.ts +++ b/src/app/call/voice.ts @@ -325,7 +325,7 @@ export const leaveVoiceRoom = async () => { try { await session.room.localParticipant.setCameraEnabled(false) } catch { - /* pass */ + pushToast({theme: "error", message: "Error turning off camera."}) } } @@ -333,7 +333,7 @@ export const leaveVoiceRoom = async () => { try { await session.room.localParticipant.setScreenShareEnabled(false) } catch { - /* pass */ + pushToast({theme: "error", message: "Error turning off screen sharing."}) } } diff --git a/src/app/components/VideoCallContent.svelte b/src/app/components/VideoCallContent.svelte index 1f69da7a..ce65a7ed 100644 --- a/src/app/components/VideoCallContent.svelte +++ b/src/app/components/VideoCallContent.svelte @@ -6,7 +6,7 @@ import Button from "@lib/components/Button.svelte" import Icon from "@lib/components/Icon.svelte" import ProfileCircle from "@app/components/ProfileCircle.svelte" - import VideoCallVideo from "@app/components/VideoCallVideo.svelte" + import VideoCallTile from "@app/components/VideoCallTile.svelte" import VoiceWidget from "@app/components/VoiceWidget.svelte" import {get} from "svelte/store" import { @@ -28,11 +28,11 @@ class?: string } - type VideoTile = { + type VideoTileData = { identity: string isLocal: boolean trackSid: string - attachable: Track | undefined + track: Track | undefined source: Track.Source.Camera | Track.Source.ScreenShare } @@ -75,7 +75,7 @@ } const room = session.room - const videoTiles: VideoTile[] = [] + const videoTiles: VideoTileData[] = [] const user = room.localParticipant if (session.cameraOn) { @@ -84,7 +84,7 @@ identity: user.identity, isLocal: true, trackSid: localPub?.trackSid ?? "local-camera", - attachable: localPub?.track, + track: localPub?.track, source: Track.Source.Camera, }) } @@ -95,7 +95,7 @@ identity: user.identity, isLocal: true, trackSid: localPub?.trackSid ?? "local-screen", - attachable: localPub?.track, + track: localPub?.track, source: Track.Source.ScreenShare, }) } @@ -107,7 +107,7 @@ identity: rp.identity, isLocal: false, trackSid: camPub.trackSid, - attachable: camPub.track, + track: camPub.track, source: Track.Source.Camera, }) } @@ -117,7 +117,7 @@ identity: rp.identity, isLocal: false, trackSid: screenPub.trackSid, - attachable: screenPub.track, + track: screenPub.track, source: Track.Source.ScreenShare, }) } @@ -127,7 +127,7 @@ }) /** Identity + source only — LiveKit can change trackSid after publish, which broke spotlight + stale-key effect. */ - const tileKey = (t: VideoTile) => `${t.identity}\x1f${t.source}` + const tileKey = (t: VideoTileData) => `${t.identity}\x1f${t.source}` const primaryTile = $derived.by(() => { const k = $videoPrimaryTileKey @@ -160,7 +160,7 @@ } }) - const labelFor = (identity: string, source: VideoTile["source"]) => { + const labelFor = (identity: string, source: VideoTileData["source"]) => { const pk = pubkeyFromLiveKitIdentity(identity) const name = pk ? displayProfileByPubkey(pk) : "Unknown" return source === Track.Source.ScreenShare ? `${name} · screen` : name @@ -183,7 +183,7 @@ ) -{#snippet videoTile(tile: VideoTile, layout: TileLayout)} +{#snippet videoTile(tile: VideoTileData, layout: TileLayout)}
- {#if tile.attachable} - diff --git a/src/app/components/VideoCallVideo.svelte b/src/app/components/VideoCallTile.svelte similarity index 66% rename from src/app/components/VideoCallVideo.svelte rename to src/app/components/VideoCallTile.svelte index ec42547e..6f8db1f9 100644 --- a/src/app/components/VideoCallVideo.svelte +++ b/src/app/components/VideoCallTile.svelte @@ -11,21 +11,21 @@ const {track, muted = true, fit = "cover", class: className = ""}: Props = $props() - let el = $state() + let videoElement = $state() $effect(() => { - const v = el - const t = track - if (!v) return - t.attach(v) + const element = videoElement + const activeTrack = track + if (!element) return + activeTrack.attach(element) return () => { - t.detach(v) + activeTrack.detach(element) } }) diff --git a/src/app/components/VoiceCallAudioSettingsDialog.svelte b/src/app/components/VoiceCallAudioSettingsDialog.svelte index 003d6814..a5fab918 100644 --- a/src/app/components/VoiceCallAudioSettingsDialog.svelte +++ b/src/app/components/VoiceCallAudioSettingsDialog.svelte @@ -41,16 +41,9 @@ } $effect(() => { - void loadDevices() - const md = navigator.mediaDevices - if (!md?.addEventListener) return - const onDeviceChange = () => { - void loadDevices() - } - md.addEventListener("devicechange", onDeviceChange) - return () => { - md.removeEventListener("devicechange", onDeviceChange) - } + loadDevices() + navigator.mediaDevices?.addEventListener?.("devicechange", loadDevices) + return () => navigator.mediaDevices?.removeEventListener?.("devicechange", loadDevices) }) $effect(() => { diff --git a/src/app/components/VoiceWidget.svelte b/src/app/components/VoiceWidget.svelte index 56f33e1a..c8601644 100644 --- a/src/app/components/VoiceWidget.svelte +++ b/src/app/components/VoiceWidget.svelte @@ -53,6 +53,14 @@ ) const routeDisplayedRoom = $derived($displayedRoomStore) + const isViewingCurrentVoiceRoom = $derived( + $currentVoiceRoom !== undefined && + url !== undefined && + typeof h === "string" && + $currentVoiceRoom.url === url && + $currentVoiceRoom.h === h, + ) + const targetRoom = $derived.by((): Room | undefined => { if ($voiceState === VoiceState.Joining || $voiceState === VoiceState.Connected) { return $currentVoiceRoom @@ -90,26 +98,17 @@ pushModal(VoiceCallAudioSettingsDialog) } - const showVoiceLayoutToggle = $derived( - $voiceState === VoiceState.Connected && - targetRoom !== undefined && - getRoomType(targetRoom) === RoomType.Voice && - typeof h === "string" && - relay !== undefined && - decodeRelay(relay) === targetRoom.url && - h === targetRoom.h, - ) + const showChatButton = $derived($voiceState === VoiceState.Connected && isViewingCurrentVoiceRoom) const isChatPanelActive = $derived( - showVoiceLayoutToggle && - ((!isDesktopLayout.current && - ($videoCallLayout === VideoCallLayout.Chat || - $videoCallLayout === VideoCallLayout.Split)) || - (isDesktopLayout.current && $videoCallLayout === VideoCallLayout.Split)), + showChatButton && + (isDesktopLayout.current + ? $videoCallLayout === VideoCallLayout.Split + : $videoCallLayout === VideoCallLayout.Chat), ) const onChatToggle = () => { - if (!showVoiceLayoutToggle) return + if (!showChatButton) return if (isDesktopLayout.current) { videoCallLayout.update(p => p === VideoCallLayout.Split ? VideoCallLayout.Video : VideoCallLayout.Split, @@ -128,17 +127,6 @@ const mediaToggleClass = "center tooltip tooltip-top btn btn-sm btn-square btn-ghost" -{#snippet mutedSlash(show: boolean)} - {#if show} - - {/if} -{/snippet} - {#if targetRoom}
- {#if showVoiceLayoutToggle} + {#if showChatButton}