From 3382579a64a9b1ab4bc5fbd00f7526fffc67c8d0 Mon Sep 17 00:00:00 2001 From: Fritz Heiden Date: Mon, 7 Apr 2025 00:16:49 +0200 Subject: [PATCH] feat: add disconnect from webrtc connection --- www/src/services/webrtc-service.js | 44 +++++++++++++++++++++++++----- www/src/views/integration-view.jsx | 43 ++++++++++++++++++++++++----- 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/www/src/services/webrtc-service.js b/www/src/services/webrtc-service.js index 124b6ba..ad0c82a 100644 --- a/www/src/services/webrtc-service.js +++ b/www/src/services/webrtc-service.js @@ -1,12 +1,20 @@ +import EventEmitter from "../tools/event-emitter"; import WebsocketService from "./websocket-service"; function WebRTCService() { const TYPE_SIGNALING = "signaling"; + const STATE_CONNECTED = "connected"; + const STATE_DISCONNECTED = "disconnected"; + const STATE_CLOSED = "closed"; + const STATE_FAILED = "failed"; + const ICE_CONNECTION_STATE_CHANGE_EVENT = "iceconnectionstatechange"; let videoElement; let peerConnection; let peerId; + let eventEmitter = new EventEmitter(); + WebsocketService.onMessage((data) => { let dataObject = JSON.parse(data); let sender = dataObject.sender; @@ -19,10 +27,15 @@ function WebRTCService() { peerId = targetId; let configuration = getConfiguration(); peerConnection = new RTCPeerConnection(configuration); - console.log("ICE connection state:" + peerConnection.iceConnectionState) - peerConnection.oniceconnectionstatechange = (event) => { - console.log("ICE connection state changed to:", peerConnection.iceConnectionState); - }; + console.log("ICE connection state:" + peerConnection.iceConnectionState); + peerConnection.addEventListener("iceconnectionstatechange", (event) => { + let state = peerConnection.iceConnectionState; + console.log("ICE connection state changed to:", state); + eventEmitter.dispatchEvent(ICE_CONNECTION_STATE_CHANGE_EVENT, state); + if (state === STATE_CONNECTED) { + videoElement.play(); + } + }); peerConnection.addEventListener("signalingstatechange", (event) => { console.log("Signaling state changed to:", event.target.signalingState); }); @@ -43,9 +56,14 @@ function WebRTCService() { peerConnection.onnegotiationneeded = () => { console.log("Negotiation needed"); negotiate(targetId); - } + }; negotiate(targetId); } + + function disconnect() { + peerConnection.close(); + eventEmitter.dispatchEvent(ICE_CONNECTION_STATE_CHANGE_EVENT, peerConnection.iceConnectionState); + } async function negotiate(targetId) { try { @@ -53,7 +71,7 @@ function WebRTCService() { offerToReceiveAudio: true, offerToReceiveVideo: true, }); - console.log("Created offer:", offer) + console.log("Created offer:", offer); await peerConnection.setLocalDescription(offer); sendOffer(targetId, offer); } catch (error) { @@ -97,7 +115,7 @@ function WebRTCService() { function handleAnswer(answer) { console.log("Remote answer:", answer); - if (peerConnection.signalingState === "stable") return + if (peerConnection.signalingState === "stable") return; peerConnection.setRemoteDescription(new RTCSessionDescription(answer)); } @@ -107,6 +125,12 @@ function WebRTCService() { peerConnection.addIceCandidate(iceCandidate); } + function onStateChanged(callback) { + eventEmitter.on(ICE_CONNECTION_STATE_CHANGE_EVENT, () => { + callback(peerConnection.iceConnectionState); + }); + } + function getConfiguration() { return { iceServers: [{ urls: "stun:stun.l.google.com:19302" }], @@ -123,9 +147,15 @@ function WebRTCService() { } return { + STATE_CONNECTED, + STATE_DISCONNECTED, + STATE_CLOSED, + STATE_FAILED, connect, + disconnect, setVideoElement, getVideoElement, + onStateChanged, }; } diff --git a/www/src/views/integration-view.jsx b/www/src/views/integration-view.jsx index 54bfbae..178d774 100644 --- a/www/src/views/integration-view.jsx +++ b/www/src/views/integration-view.jsx @@ -10,6 +10,16 @@ function IntegrationView(props) { ? integration().getName() : "Integration" ); + const [connectionState, setConnectionState] = createSignal( + WebRTCService.STATE_DISCONNECTED + ); + const showConnectButton = createMemo( + () => + connectionState() === WebRTCService.STATE_DISCONNECTED || + connectionState() === WebRTCService.STATE_FAILED || + connectionState() === WebRTCService.STATE_CLOSED + ); + WebRTCService.onStateChanged(handleConnectionStateChanged); let videoElement = null; function handleConnectWebRTC() { @@ -18,6 +28,14 @@ function IntegrationView(props) { WebRTCService.connect(integrationId); } + function handleDisconnectWebRTC() { + WebRTCService.disconnect(); + } + + function handleConnectionStateChanged(state) { + setConnectionState(state); + } + return (
{title}
- + + + + + +
@@ -40,9 +72,6 @@ function IntegrationView(props) { ref={videoElement} class="w-100 h-100" style="background-color: #000" - controls={true} - muted={false} - autoplay={true} >