UNPKG

rtcmulticonnection

Version:

RTCMultiConnection is a WebRTC JavaScript wrapper library runs top over RTCPeerConnection API to support all possible peer-to-peer features.

566 lines (464 loc) 23.9 kB
<!-- Demo version: 2017.08.06 --> <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta charset="utf-8"> <link rel="stylesheet" href="https://cdn.webrtc-experiment.com/style.css"> <title>Admin/Guest demo using RTCMultiConnection</title> <meta name="description" content="Admin/Guest demo using RTCMultiConnection" /> <meta name="keywords" content="WebRTC,RTCMultiConnection,Demos,Experiments,Samples,Examples" /> <style> video { object-fit: fill; width: 30%; } button, input, select { font-weight: normal; padding: 2px 4px; text-decoration: none; display: inline-block; text-shadow: none; font-size: 16px; outline: none; } .make-center { text-align: center; padding: 5px 10px; } .prompt-bar { background: rgb(255, 255, 255); border: 9px solid rgb(216, 216, 216); border-radius: 5px; bottom: 0; box-shadow: 0 0 5px, inset 0 0 2px; display: none; position: fixed; right: 0; width: 30%; z-index: 100; } .prompt-bar #notification-header { border-bottom: 1px solid rgb(213, 211, 211); display: block; padding: .1em .6em; } .prompt-bar #notification-text { padding: .2em .6em; } .prompt-bar #controls { background: rgb(175, 174, 174); border: 1px solid gray; text-align: center; } </style> </head> <body> <article> <header style="text-align: center;"> <h1>Admin/Guest demo using RTCMultiConnection</h1> <p> <a href="https://rtcmulticonnection.herokuapp.com/">HOME</a> <span> &copy; </span> <a href="http://www.MuazKhan.com/" target="_blank">Muaz Khan</a> . <a href="http://twitter.com/WebRTCWeb" target="_blank" title="Twitter profile for WebRTC Experiments">@WebRTCWeb</a> . <a href="https://github.com/muaz-khan?tab=repositories" target="_blank" title="Github Profile">Github</a> . <a href="https://github.com/muaz-khan/RTCMultiConnection/issues?state=open" target="_blank">Latest issues</a> . <a href="https://github.com/muaz-khan/RTCMultiConnection/commits/master" target="_blank">What's New?</a> </p> </header> <div class="github-stargazers"></div> <section class="experiment"> <div class="make-center"> <input type="text" id="admin-id" value="abcdef"> <button id="btn-become-admin">I'm Admin</button> <button id="btn-become-guest">I'm Guest</button> <div id="room-urls" style="text-align: center;display: none;background: #F1EDED;margin: 15px -10px;border: 1px solid rgb(189, 189, 189);border-left: 0;border-right: 0;"></div> <br><br> <input type="text" id="input-text-chat" placeholder="Enter Text Chat" disabled> <button id="share-file" disabled>Share File</button> </div> <div id="chat-container"> <div id="file-container"></div> <div class="chat-output"></div> </div> <div id="videos-container"></div> </section> <div id="notification-box" class="prompt-bar"> <h2 id="notification-header">Notification</h2> <p id="notification-text">Notification</p> <div id="controls"> <button id="btn-notification-accept" style="float:right;">Accept</button> <button id="btn-notification-close" style="float:left;">Close</button> <section style="color: transparent;">Control Panel</section> </div> </div> <script src="/dist/RTCMultiConnection.min.js"></script> <script src="/socket.io/socket.io.js"></script> <script src="https://cdn.webrtc-experiment.com:443/FileBufferReader.js"></script> <script> // ...................................................... // .......................UI Code........................ // ...................................................... document.getElementById('btn-become-admin').onclick = function() { disableInputButtons(); connection.adminId = document.getElementById('admin-id').value; connection.socketCustomEvent = connection.adminId; connection.checkPresence(connection.adminId, function(isAdminOnline, adminId, adminInfo) { if(isAdminOnline) { rmcNotificationBox('Multiple admins are NOT allowed. An admin is using same "admin-id".', { btnClose: false, btnAccept: false, btnAcceptText: '', onBtnAcceptClicked: function() {}, autoClose: true, autoCloseInterval: 5 * 1000 }); return; } connection.open(connection.adminId, function() { showRoomURL(connection.sessionid); }); handleSocketCustomMessages(); }); }; document.getElementById('btn-become-guest').onclick = function() { disableInputButtons(); connection.adminId = document.getElementById('admin-id').value; connection.socketCustomEvent = connection.adminId; connection.checkPresence(connection.adminId, function(isAdminOnline, adminId, adminInfo) { handleSocketCustomMessages(); if(!isAdminOnline) { rmcNotificationBox('Admin seems offline.', { btnClose: true, btnAccept: false, btnAcceptText: '', onBtnAcceptClicked: function() {}, autoClose: true, autoCloseInterval: 5 * 1000 }); return; } if(adminInfo.adminBusy) { rmcNotificationBox('Admin seems online however his status is showing "busy".', { btnClose: true, btnAccept: false, btnAcceptText: '', onBtnAcceptClicked: function() {}, autoClose: true, autoCloseInterval: 5 * 1000 }); return; } rmcNotificationBox('Admin is online. You can join him. He seems "available" as well.', { btnClose: true, btnAccept: true, btnAcceptText: 'Join Admin', onBtnAcceptClicked: function() { connection.sendCustomMessage({ messageFor: adminId, newGuest: true, guestId: connection.userid, guestInfo: connection.extra }); }, autoClose: false, autoCloseInterval: 2 * 1000 }); }); }; var notificationBox = document.getElementById('notification-box'); var notificationText = document.getElementById('notification-text'); var btnNotificationClose = document.getElementById('btn-notification-close'); var btnNotificationAccept = document.getElementById('btn-notification-accept'); function rmcNotificationBox(text, config) { notificationText.innerHTML = text; notificationBox.style.display = 'block'; if(config.btnClose && config.btnClose === true) { btnNotificationClose.style.display = 'inline-block'; } else { btnNotificationClose.style.display = 'none'; } if(config.btnAccept && config.btnAccept === true) { btnNotificationAccept.style.display = 'inline-block'; } else { btnNotificationAccept.style.display = 'none'; } if(config.btnAcceptText && config.btnAcceptText.length) { btnNotificationAccept.innerHTML = config.btnAcceptText; } else { btnNotificationAccept.innerHTML = 'Accept'; } if(config.autoClose) { setTimeout(function() { notificationBox.style.display = 'none'; }, config.autoCloseInterval || 5 * 1000); } btnNotificationClose.onclick = function() { notificationBox.style.display = 'none'; }; btnNotificationAccept.onclick = function() { notificationBox.style.display = 'none'; if(config.onBtnAcceptClicked && typeof config.onBtnAcceptClicked === 'function') { config.onBtnAcceptClicked(); } }; } // ...................................................... // ................FileSharing/TextChat Code............. // ...................................................... document.getElementById('share-file').onclick = function() { var fileSelector = new FileSelector(); fileSelector.selectSingleFile(function(file) { connection.send(file); }); }; document.getElementById('input-text-chat').onkeyup = function(e) { if (e.keyCode != 13) return; // removing trailing/leading whitespace this.value = this.value.replace(/^\s+|\s+$/g, ''); if (!this.value.length) return; connection.send(this.value); appendDIV(this.value); this.value = ''; }; var chatContainer = document.querySelector('.chat-output'); function appendDIV(event) { var div = document.createElement('div'); div.innerHTML = event.data || event; chatContainer.insertBefore(div, chatContainer.firstChild); div.tabIndex = 0; div.focus(); document.getElementById('input-text-chat').focus(); } // ...................................................... // ..................RTCMultiConnection Code............. // ...................................................... var connection = new RTCMultiConnection(); // by default, socket.io server is assumed to be deployed on your own URL connection.socketURL = '/'; // comment-out below line if you do not have your own socket.io server // connection.socketURL = 'https://rtcmulticonnection.herokuapp.com:443/'; connection.socketMessageEvent = 'admin-guest-demo'; connection.enableFileSharing = true; // by default, it is "false". connection.session = { audio: true, video: true, data: true }; connection.sdpConstraints.mandatory = { OfferToReceiveAudio: true, OfferToReceiveVideo: true }; connection.videosContainer = document.getElementById('videos-container'); connection.onstream = function(event) { connection.videosContainer.appendChild(event.mediaElement); event.mediaElement.play(); setTimeout(function() { event.mediaElement.play(); }, 5000); }; connection.onmessage = appendDIV; connection.filesContainer = document.getElementById('file-container'); connection.onopen = function() { document.getElementById('share-file').disabled = false; document.getElementById('input-text-chat').disabled = false; document.querySelector('h1').innerHTML = 'You are connected with: ' + connection.getAllParticipants().join(', '); }; connection.onclose = function() { if(connection.getAllParticipants().length) { document.querySelector('h1').innerHTML = 'You are still connected with: ' + connection.getAllParticipants().join(', '); } else { document.querySelector('h1').innerHTML = 'Seems session has been closed or all participants left.'; } }; connection.___updateExtraData = connection.updateExtraData; connection.updateExtraData = function() { connection.___updateExtraData(); connection.sendCustomMessage({ updatedExtraData: true, adminId: connection.userid, extra: connection.extra }); }; connection.onNewParticipant = function(participantId, userPreferences) { if(connection.userid === connection.adminId && !connection.extra.adminBusy) { connection.connectedGuestId = participantId; connection.extra.adminBusy = true; connection.updateExtraData(); connection.acceptParticipationRequest(participantId, userPreferences); } }; connection.onleave = function(event) { if(event.userid === connection.connectedGuestId) { connection.connectedGuestId = null; connection.extra.adminBusy = false; connection.updateExtraData(); } }; connection.sendCustomMessage = function(message) { if(!connection.socket) connection.connectSocket(); connection.socket.emit(connection.socketCustomEvent, message); }; connection.onExtraDataUpdated = function(event) { if(connection.userid == connection.adminId) return; if(event.userid === connection.adminId && event.extra.adminBusy === false) { notificationBox.style.display = 'none'; } if(connection.getAllParticipants().length) return; if(event.userid === connection.adminId && event.extra.adminBusy === false) { rmcNotificationBox('Admin is online. You can join him. He seems "available" as well.', { btnClose: true, btnAccept: true, btnAcceptText: 'Join Admin', onBtnAcceptClicked: function() { connection.sendCustomMessage({ messageFor: event.userid, newGuest: true, guestId: connection.userid, guestInfo: connection.extra }); }, autoClose: false, autoCloseInterval: 2 * 1000 }); } }; function handleSocketCustomMessages() { if(!connection.socket) connection.connectSocket(); connection.socket.on(connection.socketCustomEvent, function(message) { if(message.updatedExtraData && message.adminId === connection.adminId) { connection.onExtraDataUpdated({ userid: connection.adminId, extra: message.extra }); return; } if(message.messageFor !== connection.userid) return; if(message.newGuest) { var text = 'A new guest asked you to join him.'; text += '<br>Guest User-ID: ' + message.guestId; text += '<br>Guest Info: ' + JSON.stringify(message.guestInfo); rmcNotificationBox(text, { btnClose: true, btnAccept: true, btnAcceptText: 'Allow Guest to Join You', onBtnAcceptClicked: function() { connection.sendCustomMessage({ messageFor: message.guestId, youCanJoinAdmin: true, adminId: connection.userid, adminInfo: connection.extra }); }, autoClose: false, autoCloseInterval: 2 * 1000 }); return; } if(message.youCanJoinAdmin) { connection.join(message.adminId); var text = 'Admin accepted your request. Setting WebRTC connection...'; rmcNotificationBox(text, { btnClose: false, btnAccept: false, btnAcceptText: '', onBtnAcceptClicked: function() {}, autoClose: true, autoCloseInterval: 2 * 1000 }); return; } }); } function disableInputButtons() { document.getElementById('btn-become-admin').disabled = true; document.getElementById('btn-become-guest').disabled = true; document.getElementById('admin-id').disabled = true; } // ...................................................... // ......................Handling admin-id................ // ...................................................... function showRoomURL(adminId) { var roomHashURL = '#' + adminId; var roomQueryStringURL = '?adminId=' + adminId; var html = '<h2>Unique URL for your room:</h2><br>'; html += 'Hash URL: <a href="' + roomHashURL + '" target="_blank">' + roomHashURL + '</a>'; html += '<br>'; html += 'QueryString URL: <a href="' + roomQueryStringURL + '" target="_blank">' + roomQueryStringURL + '</a>'; var roomURLsDiv = document.getElementById('room-urls'); roomURLsDiv.innerHTML = html; roomURLsDiv.style.display = 'block'; } (function() { var params = {}, r = /([^&=]+)=?([^&]*)/g; function d(s) { return decodeURIComponent(s.replace(/\+/g, ' ')); } var match, search = window.location.search; while (match = r.exec(search.substring(1))) params[d(match[1])] = d(match[2]); window.params = params; })(); var adminId = ''; if (localStorage.getItem(connection.socketMessageEvent)) { adminId = localStorage.getItem(connection.socketMessageEvent); } else { adminId = connection.token(); } document.getElementById('admin-id').value = adminId; document.getElementById('admin-id').onkeyup = function() { localStorage.setItem(connection.socketMessageEvent, this.value); }; var hashString = location.hash.replace('#', ''); if(hashString.length && hashString.indexOf('comment-') == 0) { hashString = ''; } var adminId = params.adminId; if(!adminId && hashString.length) { adminId = hashString; } if(adminId && adminId.length) { document.getElementById('admin-id').value = adminId; localStorage.setItem(connection.socketMessageEvent, adminId); disableInputButtons(); document.getElementById('btn-become-guest').onclick(); } </script> <section class="experiment own-widgets latest-commits"> <h2 class="header" id="updates" style="color: red;padding-bottom: .1em;"><a href="https://github.com/muaz-khan/RTCMultiConnection/commits/master">Latest Updates</a></h2> <div id="github-commits"></div> </section> <section class="experiment own-widgets"> <h2 class="header" id="updates" style="color: red;padding-bottom: .1em;"><a href="https://github.com/muaz-khan/RTCMultiConnection/issues">Latest Issues</a></h2> <div id="github-issues"></div> </section> <section class="experiment"> <h2 class="header" id="feedback">Feedback</h2> <div> <textarea id="message" style="height: 8em; margin: .2em; width: 98%; border: 1px solid rgb(189, 189, 189); outline: none; resize: vertical;" placeholder="Have any message? Suggestions or something went wrong?"></textarea> </div> <button id="send-message" style="font-size: 1em;">Send Message</button><small style="margin-left:1em;">Enter your email too; if you want "direct" reply!</small> </section> <a href="https://github.com/muaz-khan/RTCMultiConnection" class="fork-left"></a> <script> window.useThisGithubPath = 'muaz-khan/RTCMultiConnection'; </script> <script src="https://cdn.webrtc-experiment.com/commits.js" async></script> </article> <footer> <p> <a href="https://www.webrtc-experiment.com">WebRTC Experiments</a> © <a href="https://plus.google.com/+MuazKhan" rel="author" target="_blank">Muaz Khan</a> <a href="mailto:muazkh@gmail.com" target="_blank">muazkh@gmail.com</a> <a href="https://github.com/muaz-khan" target="_blank">Github</a> </p> </footer> </body> </html>