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