From a2d19fe646ea27d514e71fa1ff939d8d72cae514 Mon Sep 17 00:00:00 2001 From: C4rnivore Date: Thu, 16 Oct 2025 17:42:05 +0500 Subject: [PATCH] Cameras drag and snap; --- client/src/components/SessionUsersPanel.tsx | 97 ++++++++++++++++++- client/src/components/ui/UserCamera.tsx | 2 +- .../src/components/ui/UserDevicesControls.tsx | 2 +- client/src/pages/NewSessionPage.tsx | 6 +- 4 files changed, 98 insertions(+), 9 deletions(-) diff --git a/client/src/components/SessionUsersPanel.tsx b/client/src/components/SessionUsersPanel.tsx index 6df2a05..2ab738f 100644 --- a/client/src/components/SessionUsersPanel.tsx +++ b/client/src/components/SessionUsersPanel.tsx @@ -1,5 +1,7 @@ +import { useState, useRef, useEffect } from "react"; import UserCamera from "./ui/UserCamera"; import UserDevicesControls from "./ui/UserDevicesControls"; +import clsx from "clsx"; export default function SessionUsersPanel() { const users = [ @@ -40,9 +42,98 @@ export default function SessionUsersPanel() { console.log(`Can control user ${id}`); } + const [isTop, setIsTop] = useState(false); + const [isLeft, setIsLeft] = useState(false); + const [isDragging, setIsDragging] = useState(false); + const [dragPosition, setDragPosition] = useState({ x: 0, y: 0 }); + const containerRef = useRef(null); + const dragOffset = useRef({ x: 0, y: 0 }); + + const handleMouseMove = (e: MouseEvent) => { + if (!isDragging || !containerRef.current) return; + setDragPosition({ + x: e.clientX - dragOffset.current.x, + y: e.clientY - dragOffset.current.y, + }); + }; + + const handleMouseUp = () => { + if (!isDragging || !containerRef.current) return; + + // Определяем, к какой стороне прилипнуть + const rect = containerRef.current.getBoundingClientRect(); + const centerY = rect.top + rect.height / 2; + const centerX = rect.left + rect.width / 2; + const viewportWidth = window.innerWidth; + const viewportHeight = window.innerHeight; + const shouldBeTop = centerY < viewportHeight / 2; + const shouldBeLeft = centerX < viewportWidth / 2; + + setIsDragging(false); + setIsTop(shouldBeTop); + setIsLeft(shouldBeLeft); + }; + + const handleMouseDown = (e: React.MouseEvent) => { + if (!containerRef.current) return; + const rect = containerRef.current.getBoundingClientRect(); + dragOffset.current = { + x: e.clientX - rect.left, + y: e.clientY - rect.top, + }; + setDragPosition({ + x: rect.left, + y: rect.top, + }); + setIsDragging(true); + }; + + useEffect(() => { + if (isDragging) { + window.addEventListener("mousemove", handleMouseMove); + window.addEventListener("mouseup", handleMouseUp); + } + + return () => { + window.removeEventListener("mousemove", handleMouseMove); + window.removeEventListener("mouseup", handleMouseUp); + }; + }, [isDragging]); + + const getStyle = (): React.CSSProperties => { + if (isDragging) { + return { + left: `${dragPosition.x}px`, + top: `${dragPosition.y}px`, + transition: "none", + }; + } + return { + left: isLeft ? "1.111vw" : "calc(100vw - 1.111vw)", + top: isTop ? "1.111vw" : "calc(100vh - 1.111vw)", + transform: `translate(${isLeft ? "0" : "-100%"}, ${ + isTop ? "0" : "-100%" + })`, + transition: "all 0.3s ease-out", + }; + }; + return ( -
-
+
+
{users.map((user) => ( ))} +
-
); } diff --git a/client/src/components/ui/UserCamera.tsx b/client/src/components/ui/UserCamera.tsx index a0d5cc7..9525b77 100644 --- a/client/src/components/ui/UserCamera.tsx +++ b/client/src/components/ui/UserCamera.tsx @@ -54,7 +54,7 @@ export default function UserCamera({ }} className={clsx( "aspect-square rounded-[1.667vw] bg-yellow-500 relative flex-shrink-0 pointer-events-auto", - isAdmin && "order-last" + isAdmin && "order-3" )} > {isAdmin && } diff --git a/client/src/components/ui/UserDevicesControls.tsx b/client/src/components/ui/UserDevicesControls.tsx index fc4824a..122123a 100644 --- a/client/src/components/ui/UserDevicesControls.tsx +++ b/client/src/components/ui/UserDevicesControls.tsx @@ -23,7 +23,7 @@ export default function UserDevicesControls() { } return ( -
+
} diff --git a/client/src/pages/NewSessionPage.tsx b/client/src/pages/NewSessionPage.tsx index dcacb1a..f6b49b2 100644 --- a/client/src/pages/NewSessionPage.tsx +++ b/client/src/pages/NewSessionPage.tsx @@ -126,7 +126,7 @@ function NewSessionPage() { } return ( -
+
{session.status === "started" && session.mode === "stream" && session.server?.localIp && @@ -201,9 +201,7 @@ function NewSessionPage() { -
- -
+
); }