전송 메시지 rtc 로 변경

This commit is contained in:
2025-10-22 14:57:49 +09:00
parent c5e32808f4
commit 08f6c8900d
2 changed files with 81 additions and 40 deletions

View File

@@ -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>
);
}

View File

@@ -12,7 +12,7 @@ function createWindow() {
sandbox: false
}
});
win.webContents.openDevTools();
// win.webContents.openDevTools();
if (app.isPackaged) {
win.loadFile(path.join(__dirname, 'frontend/dist/index.html'));