this is a pain in the ass
This commit is contained in:
95
hooks/useChatGPT.ts
Normal file
95
hooks/useChatGPT.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { io, Socket } from 'socket.io-client';
|
||||
|
||||
interface CursorPosition {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
interface PeerMouseHook {
|
||||
cursors: Record<string, CursorPosition>;
|
||||
}
|
||||
|
||||
export function usePeerMouse(roomId: string): PeerMouseHook {
|
||||
const [cursors, setCursors] = useState<Record<string, CursorPosition>>({});
|
||||
const socketRef = useRef<Socket | null>(null);
|
||||
const peers = useRef<Record<string, RTCPeerConnection>>({});
|
||||
const channels = useRef<Record<string, RTCDataChannel>>({});
|
||||
|
||||
useEffect(() => {
|
||||
const socket = io();
|
||||
socketRef.current = socket;
|
||||
|
||||
socket.emit('join-room', roomId);
|
||||
|
||||
socket.on('new-peer', async (peerId: string) => {
|
||||
const pc = createPeer(peerId, true);
|
||||
const offer = await pc.createOffer();
|
||||
await pc.setLocalDescription(offer);
|
||||
socket.emit('signal', { to: peerId, data: { description: pc.localDescription } });
|
||||
});
|
||||
|
||||
socket.on('signal', async ({ from, data }) => {
|
||||
const pc = peers.current[from] || createPeer(from, false);
|
||||
|
||||
if (data.description) {
|
||||
await pc.setRemoteDescription(data.description);
|
||||
|
||||
if (data.description.type === 'offer') {
|
||||
const answer = await pc.createAnswer();
|
||||
await pc.setLocalDescription(answer);
|
||||
socket.emit('signal', { to: from, data: { description: pc.localDescription } });
|
||||
}
|
||||
}
|
||||
|
||||
if (data.candidate) {
|
||||
await pc.addIceCandidate(data.candidate);
|
||||
}
|
||||
});
|
||||
|
||||
function createPeer(peerId: string, isInitiator: boolean): RTCPeerConnection {
|
||||
const pc = new RTCPeerConnection();
|
||||
|
||||
if (isInitiator) {
|
||||
const channel = pc.createDataChannel('mouse');
|
||||
setupChannel(peerId, channel);
|
||||
} else {
|
||||
pc.ondatachannel = (e) => setupChannel(peerId, e.channel);
|
||||
}
|
||||
|
||||
pc.onicecandidate = (e) => {
|
||||
if (e.candidate) {
|
||||
socket.emit('signal', { to: peerId, data: { candidate: e.candidate } });
|
||||
}
|
||||
};
|
||||
|
||||
peers.current[peerId] = pc;
|
||||
return pc;
|
||||
}
|
||||
|
||||
function setupChannel(peerId: string, channel: RTCDataChannel) {
|
||||
channels.current[peerId] = channel;
|
||||
channel.onmessage = (e) => {
|
||||
const pos = JSON.parse(e.data);
|
||||
setCursors((prev) => ({ ...prev, [peerId]: pos }));
|
||||
};
|
||||
}
|
||||
|
||||
function handleMouseMove(e: MouseEvent) {
|
||||
const pos = JSON.stringify({ x: e.clientX, y: e.clientY });
|
||||
Object.values(channels.current).forEach((ch) => {
|
||||
if (ch.readyState === 'open') ch.send(pos);
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('mousemove', handleMouseMove);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('mousemove', handleMouseMove);
|
||||
socket.disconnect();
|
||||
Object.values(peers.current).forEach((pc) => pc.close());
|
||||
};
|
||||
}, [roomId]);
|
||||
|
||||
return { cursors };
|
||||
}
|
||||
Reference in New Issue
Block a user