Skip to content

Commit 6da3e14

Browse files
committed
many videoconf rooms
1 parent 6246a36 commit 6da3e14

3 files changed

Lines changed: 442 additions & 0 deletions

File tree

videoconference/index2.html

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>BrainWeb</title>
5+
6+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
7+
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet" type="text/css">
8+
<link href="https://cdn.jsdelivr.net/npm/quasar@1.9.10/dist/quasar.min.css" rel="stylesheet" type="text/css">
9+
<link href="https://cdn.jsdelivr.net/npm/animate.css@^3.5.2/animate.min.css" rel="stylesheet">
10+
11+
<link rel="shortcut icon" type="image/x-icon" href="./favicon.ico" />
12+
<link href="https://fonts.googleapis.com/css?family=Raleway:100,300,400,500,900" rel="stylesheet">
13+
14+
<link rel="stylesheet" type="text/css" href="/css/main.css">
15+
<link rel="stylesheet" type="text/css" href="./videoconference.css">
16+
17+
<style>
18+
#q-app {
19+
margin-top:70px;
20+
}
21+
.room {
22+
color: #ccc;
23+
display: inline-block;
24+
width: 280px;
25+
height: 220px;
26+
background: #1d1d1d;
27+
border: thin solid #333;
28+
border-radius: 5px;
29+
margin: 14px 10px;
30+
text-align: center;
31+
transition: border 0.5s;
32+
}
33+
.room:hover {
34+
border: thin solid white;
35+
}
36+
.animal {
37+
font-size: 3rem;
38+
filter: saturate(0.1) contrast(1.3);
39+
margin-top: -16px;
40+
margin-bottom: 12px;
41+
margin-left: 120px;
42+
margin-right: 120px;
43+
background: #77f;
44+
border-radius: 50px;
45+
width: 50px;
46+
height: 50px;
47+
}
48+
.camera {
49+
margin: 3px;
50+
}
51+
.subject {
52+
color: white;
53+
width: calc( 100% - 20px);
54+
margin: 10px;
55+
padding: 12px;
56+
font-weight: bold;
57+
background: none;
58+
border: none;
59+
}
60+
.subject:placeholder-shown {
61+
opacity: 50%;
62+
border: 1px dashed #555;
63+
font-weight: normal;
64+
}
65+
.button {
66+
border: thin solid #555;
67+
color: white;
68+
background: #373737;
69+
padding: 5px 24px;
70+
border-radius: 20px;
71+
}
72+
.button:hover {
73+
background: #222;
74+
}
75+
#container {
76+
position: absolute;
77+
top: 50%;
78+
left: 50%;
79+
width: 100%;
80+
max-width: 940px;
81+
text-align: center;
82+
transform: translate(-50%, -50%);
83+
}
84+
</style>
85+
</head>
86+
87+
<body>
88+
89+
<!-- Firebase authentication -->
90+
<div id="firebaseui-auth-container" class="auth-dialog"></div>
91+
92+
<!-- navigation bar -->
93+
<!-- currently, the fixed top class is added, so it sticks to the top -->
94+
<!-- data value of nav bar corresponds to id in each section -->
95+
<nav class="navbar navbar-expand-lg fixed-top ">
96+
97+
<a class="navbar-brand" href="/" >
98+
<div class="logo_brainweb"><p style="padding-left:4em;color:white;cursor:pointer;font-size:14px;font-weight:300;line-height:2.7;vertical-align: middle;">BrainWeb</p></div>
99+
</a>
100+
101+
<button class="navbar-toggler landing-page myCollapsedMenuBarIcon" id="myMenuBtn" type="button" data-toggle="collapse" data-target="#myMenu" aria-controls="myMenu" aria-expanded="false" aria-label="Toggle navigation" style="padding:0;border:none; width:1.5em;height:1.5em;" onclick="this.blur();">
102+
</button>
103+
104+
<div class="collapse navbar-collapse" id="myMenu" style="width:100%;">
105+
<ul class="navbar-nav mr-4" >
106+
<li class="nav-item">
107+
<a class="nav-link" href="/">BrainWeb</a>
108+
</li>
109+
<li class="nav-item">
110+
<a class="nav-link" href="/#events">Events</a>
111+
</li>
112+
<li class="nav-item">
113+
<a class="nav-link" href="/projects/">Projects</a>
114+
</li>
115+
<li class="nav-item">
116+
<a class="nav-link" href="/community/">Community</a>
117+
</li>
118+
<li class="nav-item">
119+
<a class="nav-link" href="/videoconference/">Videoconference</a>
120+
</li>
121+
<li class="nav-item">
122+
<span class="nav-link" id="loginStatus" style="border-bottom:none"><a style="color:white" href="#" onclick="signIn()">Sign In</a></span>
123+
</li>
124+
<li class="nav-item" id="userAvatar">
125+
<img class="userIcon"/>
126+
</li>
127+
</ul>
128+
</div>
129+
</nav>
130+
131+
<div id="q-app">
132+
<!-- part 4 Videoconference rooms -->
133+
<div id="container">
134+
<div class="room" id="orangutan"><div class="animal">🦧</div><b>Orangutan</b> Room<input type=""text class="subject" placeholder="Enter Room Subject" onchange="roomRename(this);"/><button class="button" onclick="openJit('bw-orangutan', 'Orangutan');">Enter</button></div>
135+
<div class="room" id="hippo"><div class="animal">🦛</div><b>Hippo</b> Room<input type="text" class="subject" placeholder="Enter Room Subject" onchange="roomRename(this);"/><button class="button" onclick="openJit('bw-hippo', 'hippo');">Enter</button></div>
136+
<div class="room" id="squid"><div class="animal">🦑</div><b>Squid</b> Room<input type="text" class="subject" placeholder="Enter Room Subject" onchange="roomRename(this);"/><button class="button" onclick="openJit('bw-squid', 'squid');">Enter</button></div>
137+
<div class="room" id="trex"><div class="animal">🦖</div><b>T-Rex</b> Room<input type="text" class="subject" placeholder="Enter Room Subject" onchange="roomRename(this);"/><button class="button" onclick="openJit('bw-trex', 'trex');">Enter</button></div>
138+
<div class="room" id="elephant"><div class="animal">🐘</div><b>Elephant</b> Room<input type="text" class="subject" placeholder="Enter Room Subject" onchange="roomRename(this);"/><button class="button" onclick="openJit('bw-elephant', 'elephant');">Enter</button></div>
139+
<div class="room" id="sloth"><div class="animal">🦥</div><b>Sloth</b> Room<input type="text" class="subject" placeholder="Enter Room Subject" onchange="roomRename(this);"/><button class="button" onclick="openJit('bw-sloth', 'sloth');">Enter</button></div>
140+
</div>
141+
142+
</div>
143+
144+
<script src="/js/sentry.min.js" data-lazy="no"></script>
145+
<script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
146+
<script src="https://cdn.jsdelivr.net/npm/quasar@1.9.10/dist/icon-set/svg-material-icons.umd.min.js"></script>
147+
<script defer src="https://www.gstatic.com/firebasejs/ui/4.5.0/firebase-ui-auth.js"></script>
148+
<link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/4.5.0/firebase-ui-auth.css" />
149+
<script defer src="https://www.gstatic.com/firebasejs/7.12.0/firebase-app.js"></script>
150+
<script defer src="https://www.gstatic.com/firebasejs/7.12.0/firebase-auth.js"></script>
151+
<script defer src="https://www.gstatic.com/firebasejs/7.12.0/firebase-database.js"></script>
152+
<script src="https://meet.jit.si/external_api.js"></script>
153+
154+
<script defer src="/js/init-firebase.js"></script>
155+
<script type="module" src="./index2.js"></script>
156+
<script src="https://cdnjs.cloudflare.com/ajax/libs/reconnecting-websocket/1.0.0/reconnecting-websocket.min.js"></script>
157+
<script>
158+
function openJit(id, name) {
159+
window.open("room.html#"+id+"."+name);
160+
}
161+
162+
const updateVideochatIcon = (sel, count) => {
163+
const el = document.querySelector(sel);
164+
if(!el) {
165+
return;
166+
}
167+
168+
if (count === 0) {
169+
el.querySelector("text").innerHTML = "";
170+
el.querySelector(".bubble").setAttribute("fill", "rgba(255,255,255,0.4)");
171+
el.classList.remove("connected");
172+
} else {
173+
el.querySelector("text").innerHTML = count;
174+
el.querySelector(".bubble").setAttribute("fill", "rgb(0, 220, 0)");
175+
el.classList.add("connected");
176+
}
177+
}
178+
179+
function websocketDump(dump) {
180+
for(key in dump) {
181+
if(key !== "" && {}.hasOwnProperty.call(dump, key)) {
182+
console.log("dump", key, dump[key]);
183+
updateVideochatIcon(`#${key}`, parseInt(dump[key]));
184+
}
185+
}
186+
}
187+
188+
function websocketUpdate(update) {
189+
const {id: key, count} = update;
190+
191+
if (key.split("-")[0] !== "bw") {
192+
return;
193+
}
194+
195+
console.log("update", key, count);
196+
updateVideochatIcon(`#${key}`, parseInt(count));
197+
}
198+
199+
function websocketOnMessage(e) {
200+
let msg = JSON.parse(e.data);
201+
if(msg.dump) {
202+
websocketDump(msg.dump);
203+
}
204+
if(msg.update) {
205+
websocketUpdate(msg.update);
206+
}
207+
}
208+
209+
function connectToWebsocket() {
210+
wss = new ReconnectingWebSocket("wss://brainspell.org/vcrooms");
211+
wss.onopen = () => {
212+
console.log("send dump request");
213+
wss.send(JSON.stringify({action: "dump"}));
214+
}
215+
wss.onmessage = websocketOnMessage;
216+
}
217+
connectToWebsocket();
218+
</script>
219+
220+
<!-- Global site tag (gtag.js) - Google Analytics -->
221+
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-138729622-3"></script>
222+
<script>
223+
window.dataLayer = window.dataLayer || [];
224+
function gtag(){dataLayer.push(arguments);}
225+
gtag('js', new Date());
226+
gtag('config', 'UA-138729622-3');
227+
</script>
228+
229+
</body>
230+
</html>

videoconference/index2.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const configureRooms = () => {
2+
document.querySelectorAll(".room").forEach((el) => {
3+
const roomID = "bw-" + el.id;
4+
const svg = `
5+
<svg class="camera" width=48 height=32 style="display:block">
6+
<g id="${roomID}" transform="translate(0,0) scale(0.4)">
7+
<path class="bubble" d="M 31.848061,7.6290677 A 28.403238,22.039304 0 0 0 3.596657,29.668006 28.403238,22.039304 0 0 0 10.583386,44.14469 L 7.6648251,56.370967 20.270838,49.740068 A 28.403238,22.039304 0 0 0 32,51.707502 28.403238,22.039304 0 0 0 60.403343,29.668006 28.403238,22.039304 0 0 0 32,7.6290677 a 28.403238,22.039304 0 0 0 -0.151939,0 z"
8+
fill="rgba(255,255,255,0.4)"></path>
9+
<path class="video" d="m 16.837732,20.440612 v 19.377113 h 24.589197 v -8.876977 l 3.412712,1.970421 5.397084,3.11609 v -6.232178 -6.232178 l -5.397084,3.116088 -3.412712,1.970423 v -8.208802 z"
10+
fill="white" stroke-width="5"></path>
11+
<text font-size="30" x="70" y="50" fill="white"></text>
12+
<g transform="translate(30,30)"><circle cx="0" cy="0" r="1" stroke-width="0.1" fill="none" stroke="white" /></g>
13+
</g>
14+
</svg>`;
15+
el.innerHTML = svg + el.innerHTML;
16+
});
17+
};
18+
configureRooms();
19+
20+
let rooms;
21+
22+
// eslint-disable-next-line no-undef
23+
startFirebase();
24+
window.addEventListener('load', () => {
25+
// eslint-disable-next-line no-undef
26+
initApp({
27+
loginUserFn: (user) => {
28+
const { displayName, photoURL } = user;
29+
document.querySelector("#userAvatar img").src = photoURL;
30+
document.querySelector("#userAvatar").style.display = "inline-block";
31+
document.getElementById("loginStatus").innerHTML = `<span id="user">${displayName}</span> (<a style="color:white" href="#" onclick="signOut()">Sign Out</a>)`;
32+
},
33+
logoutUserFn: () => {
34+
document.querySelector("#userAvatar").style.display = "none";
35+
document.querySelector("#userAvatar img").src = "";
36+
document.getElementById("loginStatus").innerHTML = `<a style="color:white" href="#" onclick="signIn()">Sign In</a>`;
37+
document.querySelectorAll(".logged").forEach((el) => { el.classList.remove("logged"); });
38+
}
39+
});
40+
41+
rooms = firebase.database().ref('rooms');
42+
rooms.on('value', (s) => {
43+
const val = s.val();
44+
if (val === null) {
45+
return;
46+
}
47+
console.log(val);
48+
for(const key in val) {
49+
if ({}.hasOwnProperty.call(val, key)) {
50+
document.querySelector(`#${key} > .subject`).value = val[key];
51+
console.log(key, val[key]);
52+
}
53+
}
54+
});
55+
});
56+
57+
const roomRename = (ev) => {
58+
const key = ev.parentElement.id;
59+
const value = ev.value;
60+
console.log(`roomRename id=${key} value=${value}`);
61+
ev.blur();
62+
rooms.update({key: value});
63+
};
64+
window.roomRename = roomRename;

0 commit comments

Comments
 (0)