diff --git a/src/app/components/CallControlBar.svelte b/src/app/components/CallControlBar.svelte index 63421aad..0475c280 100644 --- a/src/app/components/CallControlBar.svelte +++ b/src/app/components/CallControlBar.svelte @@ -39,12 +39,9 @@ type Props = { url: string h: string - // suppress the full in-call control row on desktop — used where a wider, - // unobstructed copy of it already floats over the video panel - hideConnectedOnDesktop?: boolean } - const {url, h, hideConnectedOnDesktop = false}: Props = $props() + const {url, h}: Props = $props() const roomStore = $derived($rooms.forRoom(url, h)) const room = $derived($roomStore) @@ -67,15 +64,7 @@ const chatUnread = $derived($notifications.has(roomPath)) const isChatPanelActive = $derived($videoCallLayout === VideoCallLayout.Split) - // With chat open, the floating bar shares the video pane with the sidebar rather - // than spanning the full width — a smaller bar reads as sized for that narrower - // space instead of just looking unchanged. Sized below mobile's max-md:h-9 (36px) - // since desktop is mouse-driven, not a touch target. max-md sizing itself is - // unaffected: mobile chat is a full-screen overlay, not a space-sharing sidebar. - const compactButtonClass = $derived( - cx("max-md:h-9 max-md:w-9", isChatPanelActive && "md:h-8 md:w-8"), - ) - const iconSize = $derived(isChatPanelActive ? 3.5 : 4.5) + const buttonClass = "button button-circle max-md:h-9 max-md:w-9" const onChatToggle = () => { videoCallLayout.update(p => @@ -86,15 +75,13 @@ {#if joiningHere || connectedHere || showJoin} + place instead of pushing/jumping past each other as flex siblings. -->
{#if joiningHere}
+ class="col-start-1 row-start-1 flex h-10 items-center gap-1.5 rounded-full border border-line bg-surface/95 px-1.5 shadow-xl backdrop-blur-md"> + class="col-start-1 row-start-1 flex items-center gap-1.5 rounded-full border border-line bg-surface/95 p-1.5 shadow-xl backdrop-blur-md md:gap-2 md:p-2"> {#if $currentCallSession} {#if !Capacitor.isNativePlatform()} {/if} {/if}
{/if} {#if showJoin} -
+
- {:else} - - {/if} -
- {:else} -
- {#if parent} - - {/if} - {#if sharedEvent} - - {/if} - {#if eventToEdit} - - {/if} -
- {#key initialValues} - - {/key} - {/if} + {#if showScrollButton} +
+
- {#if h} -
- + {/if} + + {#if showFixedNewMessages} +
+ +
+ {/if} +
+ +
+
+ {#if $room?.meta?.isPrivate() && $membershipStatus !== MembershipStatus.Granted} + + {:else if $room?.meta?.isRestricted() && $membershipStatus !== MembershipStatus.Granted} +
+

Only members are allowed to post to this room.

+ {#if $membershipStatus === MembershipStatus.Pending} + + {:else} + + {/if}
+ {:else} +
+ {#if parent} + + {/if} + {#if sharedEvent} + + {/if} + {#if eventToEdit} + + {/if} +
+ {#key initialValues} + + {/key} {/if}
+ {#if h && isVoiceRoom && !voiceConnectedHere} +
+ +
+ {/if}
- -{#if showScrollButton} -
- -
-{/if} - -{#if showFixedNewMessages} -
-
- -
-
-{/if} diff --git a/src/app/components/VideoCallContent.svelte b/src/app/components/VideoCallContent.svelte index 85291466..6c9bf9be 100644 --- a/src/app/components/VideoCallContent.svelte +++ b/src/app/components/VideoCallContent.svelte @@ -7,10 +7,8 @@ import Icon from "@lib/components/Icon.svelte" import ProfileCircle from "@app/components/ProfileCircle.svelte" import VideoCallTile from "@app/components/VideoCallTile.svelte" - import CallControlBar from "@app/components/CallControlBar.svelte" import VoiceParticipantMediaBadges from "@app/components/VoiceParticipantMediaBadges.svelte" import { - VideoCallLayout, toggleVideoPrimaryTile, videoPrimaryTileKey, currentCallSession, @@ -25,8 +23,6 @@ import {deriveDisplaysByPubkey} from "@app/social" type Props = { - layout: VideoCallLayout - mobile?: boolean url: string h: string class?: string @@ -42,16 +38,7 @@ type TileLayoutVariant = "spotlight" | "default" | "strip" - const {layout, mobile = false, url, h, class: className = ""}: Props = $props() - - const isViewingCurrentCallRoom = $derived( - $callTargetRoom?.url === url && $callTargetRoom?.h === h, - ) - - const showVideoContent = $derived( - isViewingCurrentCallRoom && - (layout === VideoCallLayout.Split || layout === VideoCallLayout.Video), - ) + const {url, h, class: className}: Props = $props() const videoTiles = $derived.by(() => { const session = $currentCallSession @@ -188,24 +175,6 @@ const spotlightHandlerFor = (key: string) => () => { toggleVideoPrimaryTile(key) } - - const panelChrome = $derived( - mobile - ? cx( - "flex min-h-0 w-full flex-1 flex-col gap-2 overflow-y-auto overflow-x-hidden bg-surface px-2 pt-4 md:hidden pb-[calc(3.5rem+var(--saib))]", - className, - ) - : "flex min-h-0 w-full min-w-0 flex-1 flex-col gap-2 overflow-hidden bg-surface px-2 pb-2 pt-4", - ) - - // Desktop: `className` (the instance's own visibility/sizing, e.g. "hidden ... - // md:flex") lives on this wrapper rather than on panelChrome, so the floating - // control bar below shares its box — a `relative` box that's already sized to - // the real (chat-sidebar-aware) video pane width, since RoomChat now lays the - // chat sidebar out as a flex sibling instead of an absolute overlay. Centering - // the controls against this box (instead of the viewport) is what keeps them - // centered in the actual remaining space as that width animates open/closed. - const desktopWrapperClass = $derived(cx("relative flex min-h-0 flex-1 flex-col", className)) {#snippet videoTile(tile: VideoTileData, layout: TileLayoutVariant)} @@ -281,7 +250,7 @@
+ class="min-h-0 flex-1 overflow-y-auto [scrollbar-gutter:stable_both-edges]"> {#if tileGrid}
{#each tileGrid.rows as row, rowIndex (rowIndex)} @@ -312,36 +281,6 @@ {/if} {/snippet} -{#if showVideoContent} - {#if mobile} -
- {@render videoPanelBody()} -
- -
- -
- {:else} - -
-
- {@render videoPanelBody()} -
-
- -
-
- {/if} -{/if} +
+ {@render videoPanelBody()} +
diff --git a/src/lib/components/base.css b/src/lib/components/base.css index b723dda6..b03dc209 100644 --- a/src/lib/components/base.css +++ b/src/lib/components/base.css @@ -170,7 +170,7 @@ body.keyboard-open { body.keyboard-open .hide-on-keyboard { @apply hidden; } -body.keyboard-open .room__compose { +body.keyboard-open .room { @apply mb-0; } diff --git a/src/lib/components/chat.css b/src/lib/components/chat.css index afeab558..84f532be 100644 --- a/src/lib/components/chat.css +++ b/src/lib/components/chat.css @@ -1,30 +1,4 @@ @layer components { - /* z-popover (not z-feature) so it stacks above the overlay chat pane (also - z-popover) instead of landing behind it — same tier + later-in-DOM trick - RoomChat's "New Messages" chip already relies on. */ - .chat__scroll-down { - @apply z-popover fixed right-4 bottom-28 md:bottom-16; - padding-bottom: var(--saib); - } - - /* .chat__scroll-down is `fixed` (viewport-relative), so it ignores CallBanner's real - in-flow layout space entirely even though CallBanner shrinks the chat area above - it. Nudge the button up by CallBanner's own approximate rendered height (~3.5rem: - border-top + py-2 padding + its tallest child, the button-sm leave/mute controls) - so it clears the banner instead of landing behind it. */ - .chat__scroll-down--banner { - @apply bottom-[calc(7rem+3.5rem)] md:bottom-[calc(4rem+3.5rem)]; - } - - /* On desktop, isOverlayChat (Split layout) floats the chat pane at md:bottom-24 - in this same corner — .chat__scroll-down's default md:bottom-16 puts the - button's top edge past that pane's bottom edge, clipping into its rounded - corner. Drop below it instead. Mobile is untouched: there the pane fills - nearly the whole screen, so the button is meant to float over it. */ - .chat__scroll-down--overlay-chat { - @apply md:bottom-10; - } - .chat-bubble { @apply bg-surface-less text-content mx-1 mb-2 flex min-w-[100px] cursor-auto flex-col gap-1 rounded-2xl p-2 text-left lg:max-w-2xl; } diff --git a/src/lib/components/room.css b/src/lib/components/room.css index f754c29c..22a1541b 100644 --- a/src/lib/components/room.css +++ b/src/lib/components/room.css @@ -1,6 +1,9 @@ @layer components { .room { - @apply relative; + /* The mobile nav is fixed on top of the page, so the room view reserves its + height here rather than in each of its children — otherwise an overlaid or + floating child ends up stacking a second copy of the offset. */ + @apply relative mb-14 md:mb-0; .room__content { @apply z-feature flex max-h-screen min-h-0 w-full min-w-0 flex-col flex-col-reverse gap-2 overflow-x-hidden overflow-y-auto; @@ -19,7 +22,7 @@ } .room__compose { - @apply z-compose relative mb-14 shrink-0 md:mb-0; + @apply z-compose relative shrink-0; } .room__compose .room__compose-inner {