rework video + text chat display controls

This commit is contained in:
mplorentz
2026-04-03 10:36:14 -04:00
parent 945e853e3b
commit fef449be85
5 changed files with 154 additions and 125 deletions
+61 -8
View File
@@ -1,6 +1,7 @@
<script lang="ts">
import {readable} from "svelte/store"
import {fly} from "svelte/transition"
import {browser} from "$app/environment"
import {goto} from "$app/navigation"
import {page} from "$app/stores"
import cx from "classnames"
@@ -11,6 +12,7 @@
import Monitor from "@assets/icons/monitor.svg?dataurl"
import PhoneRounded from "@assets/icons/phone-rounded.svg?dataurl"
import PhoneCallingRounded from "@assets/icons/phone-calling-rounded.svg?dataurl"
import ChatRound from "@assets/icons/chat-round.svg?dataurl"
import CloseCircle from "@assets/icons/close-circle.svg?dataurl"
import Settings from "@assets/icons/settings.svg?dataurl"
import Icon from "@lib/components/Icon.svelte"
@@ -32,6 +34,8 @@
currentVoiceSession,
currentVoiceRoom,
voiceState,
voiceMobileRoomPanel,
voiceDesktopRoomPanel,
isLocalSpeaking,
leaveVoiceRoom,
toggleMute,
@@ -76,6 +80,45 @@
pushModal(VoiceCallAudioSettingsDialog)
}
let isMd = $state(
typeof window !== "undefined" && window.matchMedia("(min-width: 768px)").matches,
)
$effect(() => {
if (!browser) return
const mq = window.matchMedia("(min-width: 768px)")
const sync = () => {
isMd = mq.matches
}
sync()
mq.addEventListener("change", sync)
return () => mq.removeEventListener("change", sync)
})
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 layoutToggleActive = $derived(
showVoiceLayoutToggle &&
((!isMd && $voiceMobileRoomPanel === "chat") || (isMd && $voiceDesktopRoomPanel === "split")),
)
const onLayoutToggle = () => {
if (!showVoiceLayoutToggle) return
if (isMd) {
voiceDesktopRoomPanel.update(p => (p === "split" ? "chat" : "split"))
} else {
voiceMobileRoomPanel.update(p => (p === "chat" ? "video" : "chat"))
}
}
const mediaToggleClass = "center tooltip tooltip-top btn btn-sm btn-square btn-ghost"
</script>
@@ -96,18 +139,28 @@
out:fly={{y: 60, duration: 250}}
class="flex flex-col gap-2 rounded-box bg-base-100 p-3">
<div class="flex flex-col gap-0.5">
{#if $voiceState === VoiceState.Joining}
<span class="text-sm font-semibold text-warning">Joining...</span>
{:else if $voiceState === VoiceState.Connected}
<span class="text-sm font-semibold text-success">Voice Connected</span>
{:else}
<span class="text-sm font-semibold text-neutral-content">Disconnected</span>
{/if}
<div class="flex items-center justify-between gap-2">
{#if $voiceState === VoiceState.Joining}
<span class="text-sm font-semibold text-warning">Joining...</span>
{:else if $voiceState === VoiceState.Connected}
<span class="text-sm font-semibold text-success">Voice Connected</span>
{:else}
<span class="text-sm font-semibold text-neutral-content">Disconnected</span>
{/if}
{#if showVoiceLayoutToggle}
<Button
data-tip="Toggle full-screen chat ↔ video (mobile) or split view (desktop)"
class={cx(mediaToggleClass, "shrink-0", layoutToggleActive && "text-primary")}
onclick={onLayoutToggle}>
<Icon icon={ChatRound} size={4} />
</Button>
{/if}
</div>
<span class="ellipsize text-xs opacity-70">
{roomName} / {spaceName}
</span>
</div>
<div class="flex items-center gap-2">
<div class="flex flex-wrap items-center gap-2">
{#if $voiceState === VoiceState.Joining}
<span class="loading loading-spinner loading-sm"></span>
<Button