전송 메시지 rtc 로 변경
This commit is contained in:
@@ -8,10 +8,11 @@ export default function RemoteControl() {
|
||||
const [status, setStatus] = useState('disconnected'); // 'disconnected' | 'connecting' | 'connected'
|
||||
const [displays, setDisplays] = useState([]);
|
||||
const [selectedDisplay, setSelectedDisplay] = useState(null);
|
||||
const [isControlling, setIsControlling] = useState(true);
|
||||
const [isControlling, setIsControlling] = useState(false);
|
||||
|
||||
const videoRef = useRef(null);
|
||||
const socketRef = useRef(null);
|
||||
const dataChannelRef = useRef(null);
|
||||
const peerConnectionRef = useRef(null);
|
||||
const EMPLOYEE_ID = "psn14020_client";
|
||||
|
||||
@@ -46,6 +47,7 @@ export default function RemoteControl() {
|
||||
setStatus('connected');
|
||||
setIsControlling(true);
|
||||
|
||||
videoRef.current.requestFullscreen();
|
||||
})
|
||||
|
||||
socket.on('icecandidate', async(data) => {
|
||||
@@ -58,6 +60,17 @@ export default function RemoteControl() {
|
||||
setStatus('disconnected');
|
||||
});
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
setStatus('disconnected');
|
||||
setIsControlling(false);
|
||||
if(peerConnectionRef.current) {
|
||||
socket.emit('forceClose', {targetId: employeeId, server: 'client'})
|
||||
}
|
||||
peerConnectionRef.current.close();
|
||||
peerConnectionRef.current = null;
|
||||
videoRef.current.requestFullscreen();
|
||||
})
|
||||
|
||||
return () => {
|
||||
socket.disconnect();
|
||||
};
|
||||
@@ -70,6 +83,7 @@ export default function RemoteControl() {
|
||||
iceServers: [{urls: 'stun:stun.l.google.com:19302'}]
|
||||
});
|
||||
|
||||
dataChannelRef.current = await peerConnectionRef.current.createDataChannel("dataChannel", null);
|
||||
const offer = await peerConnectionRef.current.createOffer({offerToReceiveVideo: true})
|
||||
await peerConnectionRef.current.setLocalDescription(offer);
|
||||
|
||||
@@ -92,11 +106,16 @@ export default function RemoteControl() {
|
||||
socketRef.current.emit('icecandidate', {type: 'icecandidate', targetId: employeeId, server:'client', 'candidate': event.candidate});
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
let nextInput = true;
|
||||
|
||||
// 🖱️ 입력 이벤트 전달
|
||||
const handleMouseEvent = (e) => {
|
||||
if (!isControlling || !videoRef.current) return;
|
||||
e.preventDefault();
|
||||
|
||||
const video = videoRef.current;
|
||||
const rect = video.getBoundingClientRect();
|
||||
@@ -108,19 +127,31 @@ export default function RemoteControl() {
|
||||
const scaleX = 1920 / video.videoWidth;
|
||||
const scaleY = 1080 / video.videoHeight;
|
||||
|
||||
socketRef.current?.emit('inputEvent', {
|
||||
// socketRef.current?.emit('inputEvent', {
|
||||
// targetId: employeeId,
|
||||
// type: 'mouse',
|
||||
// action: e.type === 'click' ? 'click' : 'move',
|
||||
// x: x * scaleX,
|
||||
// y: y * scaleY,
|
||||
// button: e.button
|
||||
// });
|
||||
|
||||
console.log(dataChannelRef.current);
|
||||
dataChannelRef.current.send(JSON.stringify({
|
||||
targetId: employeeId,
|
||||
type: 'mouse',
|
||||
action: e.type === 'click' ? 'click' : 'move',
|
||||
x: x * scaleX,
|
||||
y: y * scaleY,
|
||||
button: e.button
|
||||
});
|
||||
}))
|
||||
|
||||
|
||||
};
|
||||
|
||||
const handleKeyDown = (e) => {
|
||||
if (!isControlling) return;
|
||||
socketRef.current?.emit('inputEvent', {
|
||||
dataChannelRef.current.send(JSON.stringify({
|
||||
targetId: employeeId,
|
||||
type: 'keyboard',
|
||||
key: e.key,
|
||||
@@ -128,7 +159,16 @@ export default function RemoteControl() {
|
||||
shiftKey: e.shiftKey,
|
||||
ctrlKey: e.ctrlKey,
|
||||
altKey: e.altKey
|
||||
});
|
||||
}))
|
||||
// socketRef.current?.emit('inputEvent', {
|
||||
// targetId: employeeId,
|
||||
// type: 'keyboard',
|
||||
// key: e.key,
|
||||
// keyCode: e.keyCode,
|
||||
// shiftKey: e.shiftKey,
|
||||
// ctrlKey: e.ctrlKey,
|
||||
// altKey: e.altKey
|
||||
// });
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -197,45 +237,46 @@ export default function RemoteControl() {
|
||||
<p style={{ fontSize: '18px', color: 'green' }}>✅ 연결 성공! 화면을 제어할 수 있습니다.</p>
|
||||
)}
|
||||
|
||||
{isControlling && (
|
||||
<div
|
||||
tabIndex={0}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '600px',
|
||||
border: '2px solid #444',
|
||||
position: 'relative',
|
||||
outline: 'none',
|
||||
backgroundColor: '#000',
|
||||
display: isControlling ? 'block' : 'none',
|
||||
}}
|
||||
onMouseMove={handleMouseEvent}
|
||||
onClick={handleMouseEvent}
|
||||
onKeyDown={handleKeyDown}
|
||||
>
|
||||
<video
|
||||
ref={videoRef}
|
||||
autoPlay
|
||||
playsInline
|
||||
muted
|
||||
controls={false}
|
||||
controlsList={'nofullscreen'}
|
||||
style={{ width: '100%', height: '100%', objectFit: 'contain' }}
|
||||
className={'fullscreen'}
|
||||
/>
|
||||
<div
|
||||
tabIndex={0}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '600px',
|
||||
border: '2px solid #444',
|
||||
position: 'relative',
|
||||
outline: 'none',
|
||||
backgroundColor: '#000'
|
||||
position: 'absolute',
|
||||
top: '12px',
|
||||
left: '12px',
|
||||
background: 'rgba(0,0,0,0.7)',
|
||||
color: 'white',
|
||||
padding: '6px 12px',
|
||||
borderRadius: '4px',
|
||||
fontSize: '16px'
|
||||
}}
|
||||
onMouseMove={handleMouseEvent}
|
||||
onClick={handleMouseEvent}
|
||||
onKeyDown={handleKeyDown}
|
||||
>
|
||||
<video
|
||||
ref={videoRef}
|
||||
autoPlay
|
||||
playsInline
|
||||
controls
|
||||
muted
|
||||
style={{ width: '100%', height: '100%', objectFit: 'contain' }}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '12px',
|
||||
left: '12px',
|
||||
background: 'rgba(0,0,0,0.7)',
|
||||
color: 'white',
|
||||
padding: '6px 12px',
|
||||
borderRadius: '4px',
|
||||
fontSize: '16px'
|
||||
}}
|
||||
>
|
||||
직원: {employeeId} | 모니터: {selectedDisplay}
|
||||
</div>
|
||||
직원: {employeeId} | 모니터: {selectedDisplay}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user