Merge branch 'fixes' into stability

This commit is contained in:
Khush Jammu 2020-06-05 19:09:12 +08:00 committed by GitHub
commit a12dd728e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 104 additions and 44 deletions

27
public/css/chat.css vendored
View File

@ -111,7 +111,9 @@ a {
#wrapper { #wrapper {
display: flex; display: flex;
flex-direction: column; /* flex: 1 1 20em; */
/* flex-basis: 30%; */
flex-direction: row;
align-items: center; align-items: center;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
@ -122,8 +124,8 @@ a {
left: 50%; left: 50%;
-ms-transform: translate(-50%, -50%); -ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
width: 65%; width: 100%;
max-height: 100%; max-height: 90vh;
max-width: 100%; max-width: 100%;
} }
@ -145,7 +147,7 @@ a {
padding: 10px; padding: 10px;
} }
#remote-video:first-child:nth-last-child(1) { #remote-video:first-child:nth-last-child(1) {
/* -or- li:only-child { */ width: min(calc(80vh * 4/3), 80vw);
max-height: 80vh; max-height: 80vh;
} }
@ -421,7 +423,22 @@ button:hover {
margin: 0; margin: 0;
line-height: 2rem; line-height: 2rem;
} }
#wrapper {
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
justify-content: center;
padding: 0;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, calc(-50% - 3rem));
max-height: 90%;
max-width: 100%;
}
#remote-video { #remote-video {
/* width: 75vw; /* width: 75vw;
height: calc((16/9) * 75vw); */ height: calc((16/9) * 75vw); */

View File

@ -37,10 +37,10 @@ var VideoChat = {
socket: io(), socket: io(),
remoteVideoWrapper: document.getElementById("wrapper"), remoteVideoWrapper: document.getElementById("wrapper"),
localVideo: document.getElementById("local-video"), localVideo: document.getElementById("local-video"),
peerColors: new Map(),
peerConnections: new Map(), peerConnections: new Map(),
recognition: undefined, recognition: undefined,
borderColor: "hsl(120,100%,70%)", borderColor: undefined,
peerColors: new Map(),
// Call to getUserMedia (provided by adapter.js for cross browser compatibility) // Call to getUserMedia (provided by adapter.js for cross browser compatibility)
// asking for access to both the video and audio streams. If the request is // asking for access to both the video and audio streams. If the request is
@ -97,21 +97,18 @@ var VideoChat = {
Snackbar.close(); Snackbar.close();
}, },
}); });
// VideoChat.borderColor = uuidToColor(VideoChat.socket.id);
VideoChat.localVideo.srcObject = stream; VideoChat.localVideo.srcObject = stream;
VideoChat.localVideo.style.border = `3px solid ${VideoChat.borderColor}`;
// Now we're ready to join the chat room. // Now we're ready to join the chat room.
VideoChat.socket.emit("join", roomHash); VideoChat.socket.emit("join", roomHash);
VideoChat.borderColor = uuidToColor(VideoChat.socket.id);
VideoChat.localVideo.style.border = `3px solid ${VideoChat.borderColor}`;
// Add listeners to the websocket // Add listeners to the websocket
VideoChat.socket.on("leave", VideoChat.onLeave); VideoChat.socket.on("leave", VideoChat.onLeave);
VideoChat.socket.on("full", chatRoomFull); VideoChat.socket.on("full", chatRoomFull);
VideoChat.socket.on("offer", VideoChat.onOffer); VideoChat.socket.on("offer", VideoChat.onOffer);
VideoChat.socket.on("willInitiateCall", VideoChat.call); VideoChat.socket.on("initiateCall", VideoChat.call);
// Set up listeners on the socket
VideoChat.socket.on("candidate", VideoChat.onCandidate); VideoChat.socket.on("candidate", VideoChat.onCandidate);
VideoChat.socket.on("answer", VideoChat.onAnswer); VideoChat.socket.on("answer", VideoChat.onAnswer);
VideoChat.socket.on("requestToggleCaptions", () => toggleSendCaptions()); VideoChat.socket.on("requestToggleCaptions", () => toggleSendCaptions());
@ -120,6 +117,7 @@ var VideoChat = {
); );
}, },
// Initiate a call with newly joined peer
call: function (uuid, room) { call: function (uuid, room) {
logIt(`call >>> Initiating call with ${uuid}...`); logIt(`call >>> Initiating call with ${uuid}...`);
VideoChat.socket.on( VideoChat.socket.on(
@ -131,6 +129,7 @@ var VideoChat = {
VideoChat.socket.emit("token", roomHash, uuid); VideoChat.socket.emit("token", roomHash, uuid);
}, },
// Handle a peer leaving the room
onLeave: function(uuid) { onLeave: function(uuid) {
logIt("disconnected - UUID " + uuid); logIt("disconnected - UUID " + uuid);
// Remove video element // Remove video element
@ -374,6 +373,12 @@ var VideoChat = {
VideoChat.connected.set(uuid, true); VideoChat.connected.set(uuid, true);
// Hide caption status text // Hide caption status text
captionText.fadeOut(); captionText.fadeOut();
// Downscale send resolution and bitrate if num in room > 4
// if (VideoChat.peerConnections.size > 3) {
// VideoChat.peerConnections.forEach(function (value, key, map) {
// downscaleStream(value);
// });
// }
// Reposition local video after a second, as there is often a delay // Reposition local video after a second, as there is often a delay
// between adding a stream and the height of the video div changing // between adding a stream and the height of the video div changing
setTimeout(() => rePositionLocalVideo(), 500); setTimeout(() => rePositionLocalVideo(), 500);
@ -512,6 +517,32 @@ function sendToAllDataChannels(message) {
// } // }
// End Fullscreen // End Fullscreen
// Downscale single stream
// async function downscaleStream(pc, applying = false) {
// height = 240;
// rate = 800000;
// if (applying) return;
// try {
// applying = true;
// do {
// h = height;
// const sender = pc.getSenders().find(function (s) {
// return s.track.kind === "video";
// });
// const ratio = sender.track.getSettings().height / height;
// const params = sender.getParameters();
// if (!params.encodings) params.encodings = [{}]; // Firefox workaround!
// params.encodings[0].scaleResolutionDownBy = Math.max(ratio, 1);
// params.encodings[0].maxBitrate = rate;
// await sender.setParameters(params);
// } while (h != height);
// } catch (e) {
// logIt(e);
// } finally {
// applying = false;
// }
// }
// Mute microphone // Mute microphone
function muteMicrophone() { function muteMicrophone() {
var audioTrack = null; var audioTrack = null;
@ -524,7 +555,7 @@ function muteMicrophone() {
}); });
audioTrack.enabled = VideoChat.audioEnabled; audioTrack.enabled = VideoChat.audioEnabled;
}); });
// select mic button and mic button text // select mic button and mic button text
const micButtonIcon = document.getElementById("mic-icon"); const micButtonIcon = document.getElementById("mic-icon");
const micButtonText = document.getElementById("mic-text"); const micButtonText = document.getElementById("mic-text");
@ -843,29 +874,33 @@ function uuidToColor(uuid) {
// Using uuid to generate random. unique pastel color // Using uuid to generate random. unique pastel color
var hash = 0; var hash = 0;
for (var i = 0; i < uuid.length; i++) { for (var i = 0; i < uuid.length; i++) {
hash = uuid.charCodeAt(i) + ((hash << 5) - hash); hash = uuid.charCodeAt(i) + ((hash << 5) - hash);
hash = hash & hash; hash = hash & hash;
} }
var hue = Math.abs(hash % 360); var hue = Math.abs(hash % 360);
// Ensure color is not similar to other colors // Ensure color is not similar to other colors
var availColors = Array.from({length: 18}, (x,i) => i*20); var availColors = Array.from({ length: 9 }, (x, i) => i * 40);
VideoChat.peerColors.forEach(function(value, key, map) {availColors[Math.floor(value/20)] = null}); VideoChat.peerColors.forEach(function (value, key, map) {
if (availColors[Math.floor(hue/20)] == null) { availColors[Math.floor(value / 40)] = null;
});
if (availColors[Math.floor(hue / 40)] == null) {
for (var i = 0; i < availColors.length; i++) { for (var i = 0; i < availColors.length; i++) {
if (availColors[i] != null) { if (availColors[i] != null) {
hue = (hue % 20) + availColors[i]; hue = (hue % 40) + availColors[i];
availColors[i] = null; availColors[i] = null;
break; break;
} }
} }
} }
return `hsl(${hue},100%,70%)`; return `hsl(${hue},100%,60%)`;
} }
// Sets the border color of uuid's stream // Sets the border color of uuid's stream
function setStreamColor(uuid) { function setStreamColor(uuid) {
const color = uuidToColor(uuid); const color = uuidToColor(uuid);
document.querySelectorAll(`[uuid="${uuid}"]`)[0].style.border = `3px solid ${color}`; document.querySelectorAll(
`[uuid="${uuid}"]`
)[0].style.border = `3px solid ${color}`;
VideoChat.peerColors[uuid] = color; VideoChat.peerColors[uuid] = color;
} }
@ -900,18 +935,27 @@ function togglePictureInPicture() {
logIt("Error exiting pip."); logIt("Error exiting pip.");
logIt(error); logIt(error);
}); });
} else if (VideoChat.remoteVideoWrapper.lastChild.webkitPresentationMode === "inline") {
VideoChat.remoteVideoWrapper.lastChild.webkitSetPresentationMode("picture-in-picture");
} else if ( } else if (
VideoChat.remoteVideoWrapper.lastChild.webkitPresentationMode === "picture-in-picture" VideoChat.remoteVideoWrapper.lastChild.webkitPresentationMode === "inline"
) { ) {
VideoChat.remoteVideoWrapper.lastChild.webkitSetPresentationMode("inline"); VideoChat.remoteVideoWrapper.lastChild.webkitSetPresentationMode(
"picture-in-picture"
);
} else if (
VideoChat.remoteVideoWrapper.lastChild.webkitPresentationMode ===
"picture-in-picture"
) {
VideoChat.remoteVideoWrapper.lastChild.webkitSetPresentationMode(
"inline"
);
} else { } else {
VideoChat.remoteVideoWrapper.lastChild.requestPictureInPicture().catch((error) => { VideoChat.remoteVideoWrapper.lastChild
alert( .requestPictureInPicture()
"You must be connected to another person to enter picture in picture." .catch((error) => {
); alert(
}); "You must be connected to another person to enter picture in picture."
);
});
} }
} else { } else {
alert( alert(
@ -934,7 +978,6 @@ window.onbeforeunload = function () {
return null; return null;
}; };
function startUp() { function startUp() {
// Try and detect in-app browsers and redirect // Try and detect in-app browsers and redirect
var ua = navigator.userAgent || navigator.vendor || window.opera; var ua = navigator.userAgent || navigator.vendor || window.opera;

15
public/landing.html vendored
View File

@ -67,9 +67,9 @@
class="mt-0 mb-32 reveal-from-bottom" class="mt-0 mb-32 reveal-from-bottom"
data-reveal-delay="300" data-reveal-delay="300"
> >
Simple, Secure, and Fast. Peer to peer group video Simple, Secure, and Fast. Peer to peer group video calling
calling provides quality and latency simply not provides quality and latency simply not available with
available with traditional technology. traditional technology.
</p> </p>
<div class="reveal-from-bottom" data-reveal-delay="450"> <div class="reveal-from-bottom" data-reveal-delay="450">
<a <a
@ -201,9 +201,8 @@
<div class="features-tiles-item-content"> <div class="features-tiles-item-content">
<h4 class="mt-0 mb-8">Decentralized group calls</h4> <h4 class="mt-0 mb-8">Decentralized group calls</h4>
<p class="m-0 text-sm"> <p class="m-0 text-sm">
Zipcall lets you talk to up to four friends by Zipcall lets you talk to up to four friends by directly
directly connecting to them, completely connecting to them, completely decentralized.
decentralized.
</p> </p>
</div> </div>
</div> </div>
@ -248,8 +247,8 @@
<h4 class="mt-0 mb-8">Total Privacy and Security</h4> <h4 class="mt-0 mb-8">Total Privacy and Security</h4>
<p class="m-0 text-sm"> <p class="m-0 text-sm">
Zipcall is built privacy first. Each chat is single use, Zipcall is built privacy first. Each chat is single use,
and end to end state of the art encryption means your calls and end to end state of the art encryption means your
are exactly that. Your calls. calls are exactly that. Your calls.
</p> </p>
</div> </div>
</div> </div>

View File

@ -8,6 +8,7 @@ var twillioAccountSID =
var twilio = require("twilio")(twillioAccountSID, twillioAuthToken); var twilio = require("twilio")(twillioAccountSID, twillioAuthToken);
var express = require("express"); var express = require("express");
var app = express(); var app = express();
const fs = require('fs');
var http = require("http").createServer(app); var http = require("http").createServer(app);
var io = require("socket.io")(http); var io = require("socket.io")(http);
var path = require("path"); var path = require("path");
@ -80,9 +81,9 @@ io.on("connection", function (socket) {
socket.join(room); socket.join(room);
} else if (numClients < 5) { } else if (numClients < 5) {
socket.join(room); socket.join(room);
// When the client is not the first to join the room, all clients are ready. logIt("Broadcasting request to connect with new peer...", room);
logIt("Broadcasting ready message", room); // Emits message to ask peers in room to connect with joining peer
socket.broadcast.to(room).emit("willInitiateCall", socket.id, room); socket.broadcast.to(room).emit("initiateCall", socket.id, room);
} else { } else {
logIt( logIt(
"room already full with " + numClients + " people in the room.", "room already full with " + numClients + " people in the room.",
@ -137,7 +138,7 @@ io.on("connection", function (socket) {
}); });
// Listen for Heroku port, otherwise just use 3000 // Listen for Heroku port, otherwise just use 3000
var port = process.env.PORT || 3000; var port = process.env.PORT || 443;
http.listen(port, function () { http.listen(port, function () {
console.log("http://localhost:" + port); console.log("http://localhost:" + port);
}); });