diff --git a/src/routes/spaces/[relay]/[h]/+layout.svelte b/src/routes/spaces/[relay]/[h]/+layout.svelte
index efbb3754..bc9b64e1 100644
--- a/src/routes/spaces/[relay]/[h]/+layout.svelte
+++ b/src/routes/spaces/[relay]/[h]/+layout.svelte
@@ -1,7 +1,14 @@
-
{#key $page.url.searchParams.get("at")}
-
+ {@render children?.()}
{/key}
diff --git a/src/routes/spaces/[relay]/[h]/+page.svelte b/src/routes/spaces/[relay]/[h]/+page.svelte
index 48b6c327..1072166f 100644
--- a/src/routes/spaces/[relay]/[h]/+page.svelte
+++ b/src/routes/spaces/[relay]/[h]/+page.svelte
@@ -13,6 +13,7 @@
import ClockCircle from "@assets/icons/clock-circle.svg?dataurl"
import InfoCircle from "@assets/icons/info-circle.svg?dataurl"
import Login2 from "@assets/icons/login-3.svg?dataurl"
+ import cx from "classnames"
import {slide, fade, fly} from "@lib/transition"
import Button from "@lib/components/Button.svelte"
import Divider from "@lib/components/Divider.svelte"
@@ -43,7 +44,8 @@
userSettingsValues,
} from "@app/core/state"
import VoiceWidget from "@app/components/VoiceWidget.svelte"
- import {VoiceState, voiceState} from "@app/voice"
+ import VideoCallContent from "@app/components/VideoCallContent.svelte"
+ import {VoiceState, currentVoiceRoom, videoTileCount, voiceState} from "@app/voice"
import {makeFeed} from "@app/core/requests"
import {popKey} from "@lib/implicit"
import {checked} from "@app/util/notifications"
@@ -56,6 +58,49 @@
const url = decodeRelay(relay)
const room = deriveRoom(url, h)
const isVoiceRoom = $derived(getRoomType($room) === RoomType.Voice)
+
+ const voiceConnectedHere = $derived(
+ isVoiceRoom &&
+ $voiceState === VoiceState.Connected &&
+ $currentVoiceRoom?.url === url &&
+ $currentVoiceRoom?.h === h,
+ )
+
+ let mobileRoomPanel = $state<"chat" | "video">("chat")
+ let voiceDesktopPanel = $state<"chat" | "video" | "split">("split")
+
+ const showMobileVideoPanel = $derived(
+ isVoiceRoom && $voiceState === VoiceState.Connected && mobileRoomPanel === "video",
+ )
+
+ const pageContentHiddenDesktopVideoOnly = $derived(
+ voiceConnectedHere && voiceDesktopPanel === "video",
+ )
+
+ let prevVideoTileCount = $state(0)
+
+ $effect(() => {
+ if ($voiceState !== VoiceState.Connected) {
+ mobileRoomPanel = "chat"
+ voiceDesktopPanel = "chat"
+ prevVideoTileCount = 0
+ return
+ }
+
+ const here = isVoiceRoom && $currentVoiceRoom?.url === url && $currentVoiceRoom?.h === h
+ const n = $videoTileCount
+
+ if (!here) {
+ prevVideoTileCount = 0
+ return
+ }
+
+ if (prevVideoTileCount === 0 && n >= 1) {
+ voiceDesktopPanel = "video"
+ mobileRoomPanel = "video"
+ }
+ prevVideoTileCount = n
+ })
const shouldProtect = canEnforceNip70(url)
const membershipStatus = deriveUserRoomMembershipStatus(url, h)
const at = $derived(parseInt($page.url.searchParams.get("at")!))
@@ -357,6 +402,40 @@
{/snippet}
{#snippet action()}
+ {#if voiceConnectedHere}
+
+
+
+
+
+
+
+
+
+ {/if}