diff --git a/public/scripts/goToRoom.js b/public/scripts/goToRoom.js index fd8c55e..a842b2c 100644 --- a/public/scripts/goToRoom.js +++ b/public/scripts/goToRoom.js @@ -1,6 +1,15 @@ import { v4 as uuidv4 } from "https://jspm.dev/uuid" +import { type } from "./utils.js" const input = document.querySelector("#go-input") + +input.addEventListener("keydown", (event) => { + if (event.code == "Space") { + event.preventDefault() + type("-") + } else if (!/^[-a-z0-9]+$/i.test(event.key)) event.preventDefault() +}) + const setHref = () => (document.querySelector("#go").href = input.value || uuidv4()) diff --git a/public/scripts/utils.js b/public/scripts/utils.js index 0b41662..4d408d7 100644 --- a/public/scripts/utils.js +++ b/public/scripts/utils.js @@ -42,7 +42,7 @@ const dragElement = (element) => { } const resizer = document.createElement("div") - resizer.className = "resizer" + resizer.classList.add("resizer") element.appendChild(resizer) resizer.addEventListener("mousedown", initDrag) resizer.addEventListener("touchstart", initDrag) @@ -58,7 +58,10 @@ const dragElement = (element) => { document.addEventListener("mouseup", () => removeFunctions()) } - element.addEventListener("mousedown", dragMouseDown) + element.addEventListener( + "mousedown", + (event) => event.button == 0 && dragMouseDown(event) + ) element.addEventListener("touchstart", dragMouseDown) } @@ -80,9 +83,14 @@ export const addVideoStream = (videoContainer, username, stream, isYours) => { videos.append(videoContainer) } -export const connectToNewUser = (userId, username, stream) => { +export const showNoVideoPrompt = () => + document.querySelector("#novideo").classList.add("show") + +export const connectToNewUser = (userId, username, stream, myPeer) => { const call = myPeer.call(userId, stream) - const video = template.content.firstElementChild.cloneNode(true) + const video = document + .querySelector("#video-template") + .content.firstElementChild.cloneNode(true) call.on("stream", (userVideoStream) => addVideoStream(video, username, userVideoStream) @@ -90,3 +98,13 @@ export const connectToNewUser = (userId, username, stream) => { call.on("close", () => video.remove()) } + +export const type = (newText) => { + const element = document.activeElement + element.setRangeText( + newText, + element.selectionStart, + element.selectionEnd, + "end" + ) +} diff --git a/public/scripts/video.js b/public/scripts/video.js index 6f492cd..508a482 100644 --- a/public/scripts/video.js +++ b/public/scripts/video.js @@ -1,31 +1,46 @@ -import { addVideoStream, connectToNewUser } from "./utils.js" +import { addVideoStream, connectToNewUser, showNoVideoPrompt } from "./utils.js" const socket = io("/") const myPeer = new Peer() const template = document.querySelector("#video-template") const yourName = localStorage.getItem("name") myPeer.on("open", async (id) => { - const stream = await navigator.mediaDevices.getUserMedia({ - video: true, - audio: true, - }) + try { + const stream = await navigator.mediaDevices.getUserMedia({ + video: true, + audio: true, + }) - const myVideo = template.content.firstElementChild.cloneNode(true) - addVideoStream(myVideo, yourName, stream, true) - myPeer.on("call", (call) => { - call.answer(stream) - const video = template.content.firstElementChild.cloneNode(true) - call.on("close", () => video.remove()) - call.on("stream", (userVideoStream) => - socket.emit("get-username", call.peer, (username) => - addVideoStream(video, username, userVideoStream) + const myVideo = template.content.firstElementChild.cloneNode(true) + addVideoStream(myVideo, yourName, stream, true) + myPeer.on("call", (call) => { + call.answer(stream) + const video = template.content.firstElementChild.cloneNode(true) + call.on("close", () => video.remove()) + call.on("stream", (userVideoStream) => + socket.emit("get-username", call.peer, (username) => + addVideoStream(video, username, userVideoStream) + ) ) - ) - }) + }) + + socket.on("user-connected", (userId, username) => + connectToNewUser(userId, username, stream, myPeer) + ) + } catch (error) { + if ( + error.name == "NotAllowedError" || + error.name == "NotFoundError" || + error.name == "PermissionDeniedError" || + error.name == "DevicesNotFoundError" + ) + return showNoVideoPrompt() + + console.log(error.name) + + throw error + } - socket.on("user-connected", (userId, username) => - connectToNewUser(userId, username, stream) - ) socket.emit("join-room", ROOM_ID, id, yourName) }) diff --git a/public/style.css b/public/style.css index 8f06032..c6240d4 100644 --- a/public/style.css +++ b/public/style.css @@ -21,7 +21,6 @@ body { height: 100vh; grid-auto-rows: 100vh; display: grid; - overflow: hidden; } #go { @@ -32,12 +31,12 @@ body { } a { - margin: 0 0.5em; text-decoration: none; width: fit-content; color: white; grid-template-columns: 1fr 500px; } + main { background-color: var(--secondary); } @@ -47,13 +46,14 @@ main { grid-template-columns: repeat(auto-fit, minmax(33%, 1fr)); grid-template-rows: repeat(auto-fit, minmax(33%, 1fr)); color: white; - padding: 4px 0 4px 0; + max-height: 100vh; + background-color: var(--secondary); gap: 2px; } video { width: 100%; - max-height: 100%; + max-height: 100vh; } .your-video { @@ -109,13 +109,6 @@ button { background-color: var(--primary); } -.medium-header { - font-size: 2.5rem; - font-weight: 200; - line-height: 1.2; - margin-bottom: 20px; -} - .button-secondary { background-color: var(--secondary); } @@ -148,12 +141,13 @@ video.your-video { } .jumbo { - margin: 20px auto; - width: 50%; + margin: 10% auto; + width: 90%; + max-width: 700px; display: flex; flex-direction: column; align-items: center; - padding: 20px 40px; + padding: 20px 30px; } .jumbo p { @@ -166,10 +160,11 @@ hr { .video .name { position: absolute; - bottom: 5px; - left: 10px; + bottom: 2vw; + left: 2vw; display: flex; - padding: 10px; + font-size: 1.5vw; + padding: 1vw; } .video.your-video .name { @@ -210,13 +205,9 @@ hr { right: -5px; } -.input-group { - display: flex; -} - .medium-header { display: flex; - font-size: 4rem; + font-size: 3em; font-weight: 250; line-height: 1.2; margin: 10px; @@ -230,9 +221,24 @@ hr { margin: 10px; } +.input-group { + display: flex; + max-width: 90%; +} + +.input-field:first-child, +.input-item:first-child { + border-radius: 5px 0 0 5px; +} + +.input-field:last-child, +.input-item:last-child { + border-radius: 0 5px 5px 0; +} + .input-field { border-left: 1px solid var(--input-border) !important; - flex: 1; + width: 90%; } .input-field:not(:first-child) { @@ -257,16 +263,6 @@ hr { padding: 0.5em 0.75em; } -.input-field:first-child, -.input-item:first-child { - border-radius: 5px 0 0 5px; -} - -.input-field:last-child, -.input-item:last-child { - border-radius: 0 5px 5px 0; -} - #is-copied.copied { opacity: 100; } @@ -284,10 +280,13 @@ hr { } } -#login { +#login, +#novideo { background-color: var(--primary); color: white; display: flex; + position: absolute; + z-index: 5; flex-direction: column; align-items: center; justify-content: center; @@ -295,13 +294,22 @@ hr { width: 100vw; } +#novideo:not(.show), #login.done { display: none; } -#login:not(.done) + div, -#login:not(.done) + div + div { - display: none !important; +#novideo p { + font-size: 1.3em; + margin: 10px auto; +} + +#novideo * { + text-align: center; +} + +#novideo a { + text-decoration: underline; } :is(textarea, input[type="text"]) { @@ -310,7 +318,7 @@ hr { background-color: transparent; border-bottom: 0.05em solid white; font-family: inherit; - font-size: 2rem; + font-size: 1.3em; max-width: 100%; max-height: 90%; } diff --git a/views/index.ejs b/views/index.ejs index 751531a..e9af0ad 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -52,17 +52,17 @@
-

Hi there

+

Video Chat


-

- Please create a new room, or join an existing room using the - form below. If a room doesn't exist it will be created.
- If a room name is not specified a random one will be - selected -

+

Enter a room name to join or create a room.

- +
+
+

No Video / Audio Device Found

+
+

+ You either denied access to a video/audio device, or one was + not found. +

+

+ Please make sure you have a microphone and webcam/camera. +
+ Once you are done please +
reload. +

+
+