feat: Implement collaboration features including user following and avatar management
This commit is contained in:
@@ -8,9 +8,9 @@ import { useActiveUsers, useSocketStore } from "../../../store/store";
|
||||
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Html } from "@react-three/drei";
|
||||
import CollabUserIcon from "../../../functions/collabUserIcon";
|
||||
import { getAvatarColor } from "../../../functions/users/functions/getAvatarColor";
|
||||
import CollabUserIcon from "./collabUserIcon";
|
||||
import useModuleStore from "../../../store/useModuleStore";
|
||||
import { getAvatarColor } from "../functions/getAvatarColor";
|
||||
|
||||
const CamModelsGroup = () => {
|
||||
const navigate = useNavigate();
|
||||
@@ -20,13 +20,14 @@ const CamModelsGroup = () => {
|
||||
const { socket } = useSocketStore();
|
||||
const { activeModule } = useModuleStore();
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const loader = new GLTFLoader();
|
||||
const dracoLoader = new DRACOLoader();
|
||||
dracoLoader.setDecoderPath("three/examples/jsm/libs/draco/gltf/");
|
||||
loader.setDRACOLoader(dracoLoader);
|
||||
|
||||
const [cams, setCams] = useState<any[]>([]);
|
||||
const [models, setModels] = useState<Record<string, { targetPosition: THREE.Vector3; targetRotation: THREE.Euler }>>({});
|
||||
const [models, setModels] = useState<Record<string, { targetPosition: THREE.Vector3; targetRotation: THREE.Euler, target: THREE.Vector3 }>>({});
|
||||
|
||||
const dedupeCams = (cams: any[]) => {
|
||||
const seen = new Set();
|
||||
@@ -102,6 +103,7 @@ const CamModelsGroup = () => {
|
||||
});
|
||||
|
||||
socket.on("cameraUpdateResponse", (data: any) => {
|
||||
|
||||
if (
|
||||
!groupRef.current ||
|
||||
socket.id === data.socketId ||
|
||||
@@ -122,6 +124,11 @@ const CamModelsGroup = () => {
|
||||
data.data.rotation.y,
|
||||
data.data.rotation.z
|
||||
),
|
||||
target: new THREE.Vector3(
|
||||
data.data.target.x,
|
||||
data.data.target.y,
|
||||
data.data.target.z
|
||||
),
|
||||
},
|
||||
}));
|
||||
});
|
||||
@@ -131,7 +138,7 @@ const CamModelsGroup = () => {
|
||||
socket.off("userDisConnectResponse");
|
||||
socket.off("cameraUpdateResponse");
|
||||
};
|
||||
}, [socket]);
|
||||
}, [email, loader, navigate, setActiveUsers, socket]);
|
||||
|
||||
useFrame(() => {
|
||||
if (!groupRef.current) return;
|
||||
@@ -217,9 +224,11 @@ const CamModelsGroup = () => {
|
||||
position={[-0.015, 0, 0.7]}
|
||||
>
|
||||
<CollabUserIcon
|
||||
userImage={cam.userData.userImage || ""}
|
||||
userImage={cam.userData.userImage ?? ""}
|
||||
userName={cam.userData.userName}
|
||||
color={getAvatarColor(index, cam.userData.userName)}
|
||||
position={cam.position}
|
||||
rotation={cam.rotation}
|
||||
/>
|
||||
</Html>
|
||||
</primitive>
|
||||
|
||||
56
app/src/modules/collaboration/camera/collabUserIcon.tsx
Normal file
56
app/src/modules/collaboration/camera/collabUserIcon.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import React from "react";
|
||||
import CustomAvatar from "../users/Avatar";
|
||||
import { useSelectedUserStore } from "../../../store/useCollabStore";
|
||||
import { useCamMode } from "../../../store/store";
|
||||
|
||||
interface CollabUserIconProps {
|
||||
userName: string;
|
||||
userImage?: string;
|
||||
color: string;
|
||||
position?: {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
};
|
||||
rotation?: {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
};
|
||||
}
|
||||
|
||||
const CollabUserIcon: React.FC<CollabUserIconProps> = ({
|
||||
userImage,
|
||||
userName,
|
||||
color,
|
||||
position,
|
||||
rotation,
|
||||
}) => {
|
||||
const { setSelectedUser } = useSelectedUserStore();
|
||||
const { setCamMode } = useCamMode();
|
||||
return (
|
||||
<div className="collab-user-live-container">
|
||||
<button
|
||||
className="user-image-container"
|
||||
onClick={() => {
|
||||
if(!position || !rotation) return;
|
||||
|
||||
// Set the selected user in the store
|
||||
setSelectedUser({ color: color, name: userName, location: { position, rotation } });
|
||||
setCamMode("FollowPerson");
|
||||
}}
|
||||
>
|
||||
{userImage ? (
|
||||
<img className="user-image" src={userImage} alt={userName} />
|
||||
) : (
|
||||
<CustomAvatar name={userName} color={color} />
|
||||
)}
|
||||
</button>
|
||||
<div className="user-name" style={{ backgroundColor: color }}>
|
||||
{userName}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CollabUserIcon;
|
||||
Reference in New Issue
Block a user