Cleanup remaining files

This commit is contained in:
mplorentz
2026-04-08 11:09:52 -04:00
parent 26069997b8
commit 288bcfe5d7
7 changed files with 62 additions and 80 deletions
-1
View File
@@ -47,7 +47,6 @@ export const isParticipantSpeaking = derived(
$participants.some(sp => participantKey(sp) === participantKey(p)),
)
/** True when the local user is in LiveKits active-speakers list (currently talking). */
export const isLocalSpeaking = derived(
[currentVoiceSession, speakingParticipants],
([$session, $speaking]) => {
+12 -18
View File
@@ -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",
})
}
}
+2 -2
View File
@@ -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."})
}
}
+14 -14
View File
@@ -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 @@
)
</script>
{#snippet videoTile(tile: VideoTile, layout: TileLayout)}
{#snippet videoTile(tile: VideoTileData, layout: TileLayout)}
<div
class={cx(
"relative isolate overflow-hidden rounded-box shadow-sm",
@@ -192,9 +192,9 @@
layout === "strip" && "aspect-video w-44 shrink-0",
tile.source === Track.Source.ScreenShare ? "bg-black" : "bg-base-100",
)}>
{#if tile.attachable}
<VideoCallVideo
track={tile.attachable}
{#if tile.track}
<VideoCallTile
track={tile.track}
muted={tile.isLocal}
fit={tile.source === Track.Source.ScreenShare ? "contain" : "cover"}
class="pointer-events-none absolute inset-0" />
@@ -11,21 +11,21 @@
const {track, muted = true, fit = "cover", class: className = ""}: Props = $props()
let el = $state<HTMLVideoElement | undefined>()
let videoElement = $state<HTMLVideoElement | undefined>()
$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)
}
})
</script>
<video
bind:this={el}
bind:this={videoElement}
class={cx("h-full w-full", fit === "contain" ? "object-contain" : "object-cover", className)}
playsinline
{muted}></video>
@@ -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(() => {
+24 -28
View File
@@ -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"
</script>
{#snippet mutedSlash(show: boolean)}
{#if show}
<span
class="pointer-events-none absolute inset-0 flex items-center justify-center overflow-visible"
aria-hidden="true">
<span class="h-[1.3px] w-[150%] max-w-none shrink-0 -rotate-45 rounded-full bg-current"
></span>
</span>
{/if}
{/snippet}
{#if targetRoom}
<div
in:fly={{y: 60, duration: 350}}
@@ -163,7 +151,7 @@
</span>
</div>
</button>
{#if showVoiceLayoutToggle}
{#if showChatButton}
<Button
data-tip="Toggle Chat"
class={cx(
@@ -206,7 +194,15 @@
onclick={toggleMute}>
<span class="relative inline-flex items-center justify-center overflow-visible">
<Icon icon={Microphone} size={4} />
{@render mutedSlash($currentVoiceSession.muted)}
{#if $currentVoiceSession.muted}
<span
class="pointer-events-none absolute inset-0 flex items-center justify-center overflow-visible"
aria-hidden="true">
<span
class="h-[1.3px] w-[150%] max-w-none shrink-0 -rotate-45 rounded-full bg-current"
></span>
</span>
{/if}
</span>
</Button>
<Button