Update environment variables for production URLs, refactor DraggableContainer to wrap children in a div when disabled, and enhance SessionUsersPanel layout with responsive adjustments for camera display. Improve UserCamera component's class handling and clean up SessionPage layout for better structure.

This commit is contained in:
2025-10-31 00:17:00 +05:00
parent 000c4caacb
commit c6157f62b2
5 changed files with 61 additions and 60 deletions
+4 -4
View File
@@ -1,4 +1,4 @@
VITE_API_URL=http://localhost:3000
VITE_WEBRTC_URL=http://localhost:3001
# VITE_API_URL=https://stream.graff.estate/api
# VITE_WEBRTC_URL=https://stream.graff.estate
# VITE_API_URL=http://localhost:3000
# VITE_WEBRTC_URL=http://localhost:3001
VITE_API_URL=https://stream.graff.estate/api
VITE_WEBRTC_URL=https://stream.graff.estate
+1 -1
View File
@@ -496,7 +496,7 @@ export default function DraggableContainer({
// Если компонент отключен, просто рендерим children без стилей и логики
if (!enabled) {
return <>{children}</>;
return <div className={className}>{children}</div>;
}
return (
+42 -46
View File
@@ -66,7 +66,7 @@ function SessionUsersPanel({
// Вычисляем количество камер для grid
const activeCamerasCount =
(localStream ? 8 : 0) +
(localStream ? 1 : 0) +
participants.filter(
(p) => p.stream != null && p.stream.getTracks().length > 0
).length;
@@ -76,19 +76,28 @@ function SessionUsersPanel({
if (count <= 2) return 1;
if (count <= 4) return 2;
if (count <= 9) return 3;
if (count <= 16) return 4;
return 5;
return 4;
};
const gridColumns = getGridColumns(activeCamerasCount);
// Вычисляем количество рядов для правильного расчета высоты
const gridRows = Math.ceil(activeCamerasCount / gridColumns);
// const gridRows = Math.ceil(activeCamerasCount / gridColumns);
// Рендерим камеры
const camerasContent = (
<>
{/* Локальная камера пользователя - показываем только если есть разрешение */}
return (
<DraggableContainer
enableSnapping={mode === "full"}
enabled={mode === "full"}
autoAlign={true}
initialCorner={innerWidth >= 640 ? "bottom-right" : "top-right"}
padding="1.111vw"
className={clsx(
"z-[999]",
mode === "full"
? "flex 2xl:gap-[0.556vw] gap-2"
: `2xl:p-[5vw] w-full max- h-dvh grid grid-cols-${gridColumns} 2xl:gap-[0.556vw] gap-2`
)}
>
{localStream && (
<UserCamera
mode={mode}
@@ -103,6 +112,7 @@ function SessionUsersPanel({
onVideoOff={toggleVideo}
onCanControl={() => console.log("Toggle control")}
onSpeakingChange={handleSpeakingChange}
className={activeCamerasCount <= 2 ? "m-auto" : " w-full"}
/>
)}
@@ -115,6 +125,7 @@ function SessionUsersPanel({
)
.map((participant) => (
<UserCamera
className={activeCamerasCount <= 2 ? "m-auto" : " w-full"}
key={participant.id}
mode={mode}
name={participant.id}
@@ -141,47 +152,32 @@ function SessionUsersPanel({
isVideoMuted={isLocalVideoMuted}
hasLocalStream={hasLocalStream}
/>
</>
</DraggableContainer>
);
// Для режима full используем DraggableContainer
if (mode === "full") {
return (
<DraggableContainer
enableSnapping={true}
enabled={true}
autoAlign={true}
initialCorner={innerWidth >= 640 ? "bottom-right" : "top-right"}
padding="1.111vw"
className="z-[999] flex gap-4"
>
{camerasContent}
</DraggableContainer>
);
}
// }
// Для режима mini используем flex-обертку для центрирования и внутри grid
return (
<div className="flex justify-center items-center w-full h-full z-[99]a">
<div
className={clsx(
"grid 2xl:gap-[0.556vw] gap-2",
gridColumns === 1 && "grid-cols-1 2xl:w-[45vw] w-[calc(50vw-1rem)]",
gridColumns === 2 && "grid-cols-2 2xl:w-[90vw] w-[calc(100vw-2rem)]",
gridColumns === 3 && "grid-cols-3 2xl:w-[90vw] w-[calc(100vw-2rem)]",
gridColumns === 4 && "grid-cols-4 2xl:w-[90vw] w-[calc(100vw-2rem)]",
gridColumns === 5 && "grid-cols-5 2xl:w-[90vw] w-[calc(100vw-2rem)]",
gridRows === 1 && "auto-rows-[calc((86vh-1.111vw)/1)]",
gridRows === 2 && "auto-rows-[calc((86vh-1.667vw)/2)]",
gridRows === 3 && "auto-rows-[calc((86vh-2.222vw)/3)]",
gridRows === 4 && "auto-rows-[calc((86vh-2.778vw)/4)]",
gridRows === 5 && "auto-rows-[calc((86vh-3.333vw)/5)]"
)}
>
{camerasContent}
</div>
</div>
);
// return (
// <div className="flex justify-center items-center w-full h-full z-[99]a">
// <div
// className={clsx(
// "grid 2xl:gap-[0.556vw] gap-2",
// gridColumns === 1 && "grid-cols-1 2xl:w-[45vw] w-[calc(50vw-1rem)]",
// gridColumns === 2 && "grid-cols-2 2xl:w-[90vw] w-[calc(100vw-2rem)]",
// gridColumns === 3 && "grid-cols-3 2xl:w-[90vw] w-[calc(100vw-2rem)]",
// gridColumns === 4 && "grid-cols-4 2xl:w-[90vw] w-[calc(100vw-2rem)]",
// gridColumns === 5 && "grid-cols-5 2xl:w-[90vw] w-[calc(100vw-2rem)]",
// gridRows === 1 && "auto-rows-[calc((86vh-1.111vw)/1)]",
// gridRows === 2 && "auto-rows-[calc((86vh-1.667vw)/2)]",
// gridRows === 3 && "auto-rows-[calc((86vh-2.222vw)/3)]",
// gridRows === 4 && "auto-rows-[calc((86vh-2.778vw)/4)]",
// gridRows === 5 && "auto-rows-[calc((86vh-3.333vw)/5)]"
// )}
// >
// {camerasContent}
// </div>
// </div>
// );
}
export default SessionUsersPanel;
+10 -4
View File
@@ -75,9 +75,13 @@ export default function UserCamera({
// Отправляем изменения состояния для локального пользователя
// Используем ref для отслеживания предыдущего состояния, чтобы избежать лишних вызовов
const prevLocalSpeakingRef = useRef<boolean>(localSpeaking);
useEffect(() => {
if (isLocal && onSpeakingChange && prevLocalSpeakingRef.current !== localSpeaking) {
if (
isLocal &&
onSpeakingChange &&
prevLocalSpeakingRef.current !== localSpeaking
) {
prevLocalSpeakingRef.current = localSpeaking;
onSpeakingChange(localSpeaking);
}
@@ -276,7 +280,7 @@ export default function UserCamera({
className={clsx(
mode === "full"
? "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 flex-shrink-0 pointer-events-auto w-full h-full object-contain",
: "aspect-video 2xl:rounded-[2.222vw] rounded-[32px] overflow-hidden group relative pointer-events-auto max-w-full h-full object-cover",
isLocal && "order-last",
isVideoOff ? "bg-green-500" : "bg-yellow-500/10",
className
@@ -290,7 +294,9 @@ export default function UserCamera({
window.innerWidth >= 1536 ? "0.069vw" : "1px"
} rgba(255, 255, 255, 0.3)`,
transition:
"box-shadow 0.1s ease-out, width 0.3s, background-color 0.3s",
mode === "full"
? "box-shadow 0.1s ease-out, width 0.3s, background-color 0.3s"
: undefined,
}}
onClick={handleVideoClick}
>
+4 -5
View File
@@ -80,7 +80,6 @@ function SessionPage() {
const session = sessionData?.session;
function handleChatOpen() {
console.log("handleChatOpen");
setPopup(<ChatPopup sessionId={id} />);
}
@@ -156,9 +155,9 @@ function SessionPage() {
return (
<div
className={clsx(
mode === "full"
? "flex overflow-hidden relative order-3 w-screen h-dvh bg-black justify-center_items-center touch-none"
: "2xl:px-[5vw] grid 2xl:gap-[0.556vw] gap-2 bg-black relative w-screen h-dvh overflow-hidden"
// "flex overflow-hidden relative order-3 w-screen h-dvh bg-black touch-none"
"overflow-hidden relative order-3 w-screen h-dvh bg-black touch-none",
mode === "full" && "flex"
)}
>
{/* Pixel Streaming - показывается только когда сессия активна */}
@@ -166,7 +165,7 @@ function SessionPage() {
session.mode === "stream" &&
session.server?.localIp &&
session.playerPort && (
<div className="absolute w-full h-full aspect-video">
<div className="absolute w-full h-full aspect-video bg-green-950">
<PixelStreamingWrapper
initialSettings={{
ss: `ws://${session.server.localIp}:${session.playerPort}`,