From 0964d650a4721875411ab9f4f9d858ed739f7b28 Mon Sep 17 00:00:00 2001 From: Lanskikh Date: Sat, 1 Nov 2025 13:27:42 +0500 Subject: [PATCH] Enhance DraggableContainer to set initial position based on bounding rectangle and update SessionUsersPanel to limit local cameras to one. Refactor UserCamera styling for consistency and improve PopoverWrapper positioning logic. Clean up unnecessary code in SessionUsersPanel for better readability. --- client/src/components/DraggableContainer.tsx | 11 +- client/src/components/SessionUsersPanel.tsx | 151 +++++++++---------- client/src/components/ui/PopoverWrapper.tsx | 5 +- client/src/components/ui/UserCamera.tsx | 7 +- 4 files changed, 82 insertions(+), 92 deletions(-) diff --git a/client/src/components/DraggableContainer.tsx b/client/src/components/DraggableContainer.tsx index 73d2473..d2d0e1b 100644 --- a/client/src/components/DraggableContainer.tsx +++ b/client/src/components/DraggableContainer.tsx @@ -446,6 +446,15 @@ export default function DraggableContainer({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [isDragging]); + useEffect(() => { + if (!containerRef.current) return; + const rect = containerRef.current.getBoundingClientRect(); + setPosition({ + top: rect.top, + left: rect.left, + }); + }, []); + // Устанавливаем cursor стили на элемент-хэндл useEffect(() => { if (!draggable || !dragHandleRef?.current) return; @@ -496,7 +505,7 @@ export default function DraggableContainer({ // Если компонент отключен, просто рендерим children без стилей и логики if (!enabled) { - return <>{children}; + return
{children}
; } return ( diff --git a/client/src/components/SessionUsersPanel.tsx b/client/src/components/SessionUsersPanel.tsx index 323ce98..3c9138d 100644 --- a/client/src/components/SessionUsersPanel.tsx +++ b/client/src/components/SessionUsersPanel.tsx @@ -5,7 +5,7 @@ import { useWebRTC } from "../hooks/useWebRTC"; import clsx from "clsx"; import { useEffect, useRef, useState } from "react"; -const LOCAL_CAMERAS_COUNT = 10; +const LOCAL_CAMERAS_COUNT = 1; interface SessionUsersPanelProps { roomId: string; @@ -157,91 +157,76 @@ function SessionUsersPanel({ windowDimensions.width >= 640 ? "bottom-right" : "top-right" } padding="1.111vw" - // className={clsx( - // "z-[100] 2xl:gap-[0.556vw] gap-2", - // mode === "mini" - // ? "flex" - // : `2xl:p-[5vw] p-4 w-full 2xl:h-dvh max-2xl:portrait:max-h-[calc(100dvh-17.778vw)] max-2xl:landscape:max-h-[calc(100dvh-8.75vw)] grid grid-cols-${gridColumns} relative bg-black` - // )} + className={clsx( + "z-[100] 2xl:gap-[0.556vw] gap-2", + mode === "mini" + ? "flex" + : `2xl:p-[2.778vw_5vw_5vw] p-[12px_12px_72px] w-full 2xl:h-dvh grid grid-cols-${gridColumns} relative 2xl:bg-black auto-rows-fr` + )} > -
- {localStream && - Array.from({ length: LOCAL_CAMERAS_COUNT }).map((_, index) => ( - console.log("Toggle control")} - onSpeakingChange={handleSpeakingChange} - className={clsx( - mode === "full" && activeCamerasCount <= 2 - ? "m-auto" - : activeCamerasCount > 12 - ? "!aspect-square w-full" - : "w-full" - )} - /> - ))} + {mode === "full" &&
} + {localStream && + Array.from({ length: LOCAL_CAMERAS_COUNT }).map((_, index) => ( + console.log("Toggle control")} + onSpeakingChange={handleSpeakingChange} + className={clsx( + mode === "full" && + (activeCamerasCount <= 2 ? "m-auto" : "min-w-full min-h-full") + )} + /> + ))} - {/* Камеры удаленных участников - показываем только если есть поток с активными треками */} - {participants - .filter( - (participant) => - participant.stream != null && - participant.stream.getTracks().length > 0 - ) - .map((participant) => ( - 12 - ? "!aspect-square w-full" - : "w-full") - )} - key={participant.id} - mode={mode} - name={participant.id} - isMuted={participant.isMuted || false} - isVideoOff={participant.isVideoOff || false} - isSpeaking={participant.isSpeaking} - isControlDisabled={true} - isAdmin={true} - mediaStream={participant.stream} - hasLocalMediaPermission={hasLocalStream} - onMute={() => console.log(`Mute user ${participant.id}`)} - onVideoOff={() => console.log(`Video off user ${participant.id}`)} - onCanControl={() => - console.log(`Can control user ${participant.id}`) - } - /> - ))} + {/* Камеры удаленных участников - показываем только если есть поток с активными треками */} + {participants + .filter( + (participant) => + participant.stream != null && + participant.stream.getTracks().length > 0 + ) + .map((participant) => ( + console.log(`Mute user ${participant.id}`)} + onVideoOff={() => console.log(`Video off user ${participant.id}`)} + onCanControl={() => + console.log(`Can control user ${participant.id}`) + } + /> + ))} - -
+ ); } diff --git a/client/src/components/ui/PopoverWrapper.tsx b/client/src/components/ui/PopoverWrapper.tsx index fca7117..4e65c86 100644 --- a/client/src/components/ui/PopoverWrapper.tsx +++ b/client/src/components/ui/PopoverWrapper.tsx @@ -28,6 +28,7 @@ function PopoverWrapper({ (position === "side" || position === "vertical") ) { const buttonRect = parentElRef.current.getBoundingClientRect(); + console.log(buttonRect); const spaceBelow = window.innerHeight - buttonRect.bottom; const spaceAbove = buttonRect.top; setOpenUpwards(spaceBelow < menuHeight && spaceAbove > menuHeight); @@ -99,9 +100,7 @@ function PopoverWrapper({ }} style={getPositionStyles()} className={clsx( - "fixed z-[99999] shadow-[0_4px_40px_0_rgba(15,16,17,0.1)] overflow-hidden bg-white 2xl:rounded-[1.111vw] rounded-2xl", - position === "side" && "-translate-x-full", - position === "vertical" && "-translate-x-full", + "fixed z-[99999] shadow-[0_4px_40px_0_rgba(15,16,17,0.1)] overflow-hidden bg-white 2xl:rounded-[1.111vw] rounded-2xl -translate-x-full", className )} > diff --git a/client/src/components/ui/UserCamera.tsx b/client/src/components/ui/UserCamera.tsx index 799d136..70c9553 100644 --- a/client/src/components/ui/UserCamera.tsx +++ b/client/src/components/ui/UserCamera.tsx @@ -280,7 +280,7 @@ export default function UserCamera({ className={clsx( mode === "mini" ? "aspect-square h-fit group 2xl:rounded-[1.667vw] rounded-2xl relative flex-shrink-0 pointer-events-auto 2xl:hover:w-[10.833vw] 2xl:w-[6.944vw] sm:w-[15.625vw] w-[27.778vw] overflow-hidden" - : "aspect-video 2xl:rounded-[2.222vw] rounded-[32px] overflow-hidden group relative pointer-events-auto max-w-full h-full self-center object-cover", + : "aspect-video 2xl:rounded-[1.667vw] rounded-2xl overflow-hidden group relative pointer-events-auto max-w-full 2xl:h-full object-cover", isLocal && "order-last", isVideoOff ? "bg-green-500" : "bg-yellow-500/10", className @@ -302,10 +302,7 @@ export default function UserCamera({ > {isLocal && } -
+
{name}