From 0bb3aa28b11452a07519b51e36c78b8d82537307 Mon Sep 17 00:00:00 2001 From: Cody Larkin Date: Sat, 28 Mar 2026 05:18:05 -0400 Subject: [PATCH] updated and connected webview to C# --- RelayClient/MainPage.xaml | 10 +- RelayClient/MainPage.xaml.cs | 69 +++++++++ RelayClient/MauiProgram.cs | 3 +- RelayClient/Resources/Raw/test.css | 24 ++- RelayClient/Resources/Raw/test.html | 48 +++++- RelayClient/Resources/Raw/test.js | 154 +++++++++++++++++-- RelayClient/Resources/Raw/wwwroot/index.css | 0 RelayClient/Resources/Raw/wwwroot/index.html | 124 +++++++++++++++ 8 files changed, 411 insertions(+), 21 deletions(-) create mode 100644 RelayClient/Resources/Raw/wwwroot/index.css create mode 100644 RelayClient/Resources/Raw/wwwroot/index.html diff --git a/RelayClient/MainPage.xaml b/RelayClient/MainPage.xaml index 86a54b9..0444499 100644 --- a/RelayClient/MainPage.xaml +++ b/RelayClient/MainPage.xaml @@ -59,7 +59,15 @@ StrokeThickness="1" Padding="10" IsVisible="False"> - + + + - + + + + + + + WebRTC Demo + + +

1. Start your Webcam

+
+ +

Local Stream

+ +
+ +

Remote Stream

+ +
+ + +
+ + +

2. Create a new Call

+ + +

3. Join a Call

+

Answer the call from a different browser window or device

+ + + + +

4. Hangup

+ + + + + + \ No newline at end of file diff --git a/RelayClient/Resources/Raw/test.js b/RelayClient/Resources/Raw/test.js index 9d0408f..c005f6b 100644 --- a/RelayClient/Resources/Raw/test.js +++ b/RelayClient/Resources/Raw/test.js @@ -1,10 +1,146 @@ -var toggle = true; +import './test.css'; -function onClicked() -{ - if (toggle) - document.getElementById("header").style.color = "green"; - else - document.getElementById("header").style.color = "red"; - toggle = !toggle; -} \ No newline at end of file +import firebase from 'firebase/app'; +import 'firebase/firestore'; + +const firebaseConfig = { + // your config +}; + +if (!firebase.apps.length) { + firebase.initializeApp(firebaseConfig); +} +const firestore = firebase.firestore(); + +const servers = { + iceServers: [ + { + urls: ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302'], + }, + ], + iceCandidatePoolSize: 10, +}; + +// Global State +const pc = new RTCPeerConnection(servers); +let localStream = null; +let remoteStream = null; + +// HTML elements +const webcamButton = document.getElementById('webcamButton'); +const webcamVideo = document.getElementById('webcamVideo'); +const callButton = document.getElementById('callButton'); +const callInput = document.getElementById('callInput'); +const answerButton = document.getElementById('answerButton'); +const remoteVideo = document.getElementById('remoteVideo'); +const hangupButton = document.getElementById('hangupButton'); + +// 1. Setup media sources + +webcamButton.onclick = async () => { + localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }); + remoteStream = new MediaStream(); + + // Push tracks from local stream to peer connection + localStream.getTracks().forEach((track) => { + pc.addTrack(track, localStream); + }); + + // Pull tracks from remote stream, add to video stream + pc.ontrack = (event) => { + event.streams[0].getTracks().forEach((track) => { + remoteStream.addTrack(track); + }); + }; + + webcamVideo.srcObject = localStream; + remoteVideo.srcObject = remoteStream; + + callButton.disabled = false; + answerButton.disabled = false; + webcamButton.disabled = true; +}; + +// 2. Create an offer +callButton.onclick = async () => { + // Reference Firestore collections for signaling + const callDoc = firestore.collection('calls').doc(); + const offerCandidates = callDoc.collection('offerCandidates'); + const answerCandidates = callDoc.collection('answerCandidates'); + + callInput.value = callDoc.id; + + // Get candidates for caller, save to db + pc.onicecandidate = (event) => { + event.candidate && offerCandidates.add(event.candidate.toJSON()); + }; + + // Create offer + const offerDescription = await pc.createOffer(); + await pc.setLocalDescription(offerDescription); + + const offer = { + sdp: offerDescription.sdp, + type: offerDescription.type, + }; + + await callDoc.set({ offer }); + + // Listen for remote answer + callDoc.onSnapshot((snapshot) => { + const data = snapshot.data(); + if (!pc.currentRemoteDescription && data?.answer) { + const answerDescription = new RTCSessionDescription(data.answer); + pc.setRemoteDescription(answerDescription); + } + }); + + // When answered, add candidate to peer connection + answerCandidates.onSnapshot((snapshot) => { + snapshot.docChanges().forEach((change) => { + if (change.type === 'added') { + const candidate = new RTCIceCandidate(change.doc.data()); + pc.addIceCandidate(candidate); + } + }); + }); + + hangupButton.disabled = false; +}; + +// 3. Answer the call with the unique ID +answerButton.onclick = async () => { + const callId = callInput.value; + const callDoc = firestore.collection('calls').doc(callId); + const answerCandidates = callDoc.collection('answerCandidates'); + const offerCandidates = callDoc.collection('offerCandidates'); + + pc.onicecandidate = (event) => { + event.candidate && answerCandidates.add(event.candidate.toJSON()); + }; + + const callData = (await callDoc.get()).data(); + + const offerDescription = callData.offer; + await pc.setRemoteDescription(new RTCSessionDescription(offerDescription)); + + const answerDescription = await pc.createAnswer(); + await pc.setLocalDescription(answerDescription); + + const answer = { + type: answerDescription.type, + sdp: answerDescription.sdp, + }; + + await callDoc.update({ answer }); + + offerCandidates.onSnapshot((snapshot) => { + snapshot.docChanges().forEach((change) => { + console.log(change); + if (change.type === 'added') { + let data = change.doc.data(); + pc.addIceCandidate(new RTCIceCandidate(data)); + } + }); + }); +}; \ No newline at end of file diff --git a/RelayClient/Resources/Raw/wwwroot/index.css b/RelayClient/Resources/Raw/wwwroot/index.css new file mode 100644 index 0000000..e69de29 diff --git a/RelayClient/Resources/Raw/wwwroot/index.html b/RelayClient/Resources/Raw/wwwroot/index.html new file mode 100644 index 0000000..795408d --- /dev/null +++ b/RelayClient/Resources/Raw/wwwroot/index.html @@ -0,0 +1,124 @@ + + + + + + + + + + + + + +
+ Hybrid sample! +
+
+ +
+
+ + + + +
+
+ + + + +
+
+ Log: +
+
+ Consider checking out this PDF: sample.pdf +
+ + \ No newline at end of file