Browse Source

Migrate web client layout to CSS grid

wip
Trevor Slocum 3 years ago
parent
commit
9ef032c1ec
  1. 2
      README.md
  2. 2
      goreleaser.yml
  3. 116
      pkg/web/public/assets/css/harmony.css
  4. 48
      pkg/web/public/assets/js/harmony.js
  5. 107
      pkg/web/public/index.html

2
README.md

@ -29,7 +29,7 @@ Please share suggestions/issues [here](https://todo.sr.ht/~tslocum/harmony).
## Libraries
The following libraries are used to build netris:
The following libraries are used to build harmony:
* [webrtc](https://github.com/pion/webrtc) - WebRTC connections and audio
* [websocket](https://github.com/gorilla/websocket) - WebSocket connections

2
goreleaser.yml

@ -9,7 +9,7 @@ builds:
binary: harmony-server
main: ./cmd/harmony-server
flags:
- -tags="embed"
- -tags=embed
ldflags:
- -s -w -X git.sr.ht/~tslocum/harmony/pkg/config.Version={{.Version}}
goos:

116
pkg/web/public/assets/css/harmony.css

@ -1,24 +1,101 @@
* {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
body {
margin: 0;
nav ul, aside ul {
list-style: none;
padding: 0;
margin: 0 0 0 5px;
}
.content {
grid-area: content;
}
.sideleft {
grid-area: sideleft;
overflow-x: auto;
overflow-y: scroll;
}
textarea {
.sideright {
grid-area: sideright;
overflow-x: auto;
overflow-y: scroll;
}
.status {
grid-area: status;
}
.footer {
grid-area: footer;
}
.wrapper {
margin: 0;
resize: none;
width: 100vw;
height: 100vh;
display: grid;
grid-gap: 0;
grid-template-areas: "sideleft" "sideright" "content" "status" "footer";
font: 1.2em Helvetica, arial, sans-serif;
}
* {
font-size: 22pt;
@media (min-height: 500px) {
.wrapper {
grid-template-rows: min-content 1fr 1fr 2fr min-content min-content;
}
}
@media (min-width: 500px) {
.wrapper {
grid-template-columns: 1fr 4fr;
grid-template-rows: 1fr 1fr min-content min-content;
grid-template-areas: "sideleft content" "sideright content" "status content" "footer footer";
}
nav ul {
display: flex;
justify-content: space-between;
}
}
@media (min-width: 700px) {
.wrapper {
grid-template-columns: 1fr 5fr 1fr;
grid-template-rows: 1fr min-content min-content;
grid-template-areas: "sideleft content sideright" "status content sideright" "footer footer footer"
}
nav ul {
flex-direction: column;
}
}
.sideleft, .sideright, .status, .content, .footer {
padding: 7px;
}
.sideleft, .sideright, .status {
min-width: 150px;
}
td {
vertical-align: top;
.content {
padding-left: 10px;
padding-right: 10px;
}
button {
@ -26,38 +103,22 @@ button {
padding: 7px;
}
#chatcontainer {
height: 100%;
button, #chathistory, #chatinput {
font-size: 1.25em;
}
#chathistory {
overflow-x: auto;
overflow-y: scroll;
display: inline-block;
width: 100%;
max-height: 100%;
font-family: monospace;
}
#inputheader, #inputfooter {
height: 15px;
}
#inputcontainer {
padding-top: 7px;
padding-bottom: 7px;
}
#chatinput {
width: 100%;
height: 100%;
border: 0;
}
#voicepttcontainer {
height: 70px;
resize: none;
}
#voiceptt {
@ -66,3 +127,4 @@ button {
margin-top: 7px;
margin-bottom: 14px;
}

48
pkg/web/public/assets/js/harmony.js

@ -31,7 +31,7 @@ var audioTrack;
var shownPTTHelp = false;
var muteOnMouseUp = true;
var userListStatus = '';
var userListStatus = 'Loading...';
var MessageBinary = 2;
var MessagePing = 100;
@ -123,7 +123,13 @@ $(document).ready(function () {
return false;
});
$("#inputheader, #inputcontainer, #inputfooter").on("click", function (e) {
$("#inputheader, #inputfooter").on("click touchstart", function (e) {
$("#chatinput").focus();
return false;
});
$("#chatinput").on("touchstart", function (e) {
$("#chatinput").focus();
return false;
@ -149,7 +155,7 @@ $(document).ready(function () {
$('#voiceactiveright').css('display', 'none');
$('#voiceButton').html('Join voice chat');
updateVoiceStatus();
updateUserStatus();
});
window.setInterval(() => {
@ -233,7 +239,7 @@ function createPeerConnection(id) {
if (id == 0 && !shownPTTHelp) {
shownPTTHelp = true;
Log("* Note: Push-to-talk is bound to <F8>");
Log("Note: Push-to-talk is bound to <F8>");
}
$('#voicepttcontainer').css('display', 'table-row');
@ -243,7 +249,7 @@ function createPeerConnection(id) {
$('#voiceactiveright').css('display', 'inline-block');
$('#voiceButton').html('Quit voice chat');
updateVoiceStatus();
updateUserStatus();
};
if (id == 0) {
@ -302,7 +308,10 @@ function Connect() {
return;
}
Log("* Connecting...");
userListStatus = 'Connecting...';
updateUserStatus();
Log("Connecting...");
var loc = window.location, wsurl, pathname;
if (loc.protocol === "https:") {
@ -319,7 +328,7 @@ function Connect() {
socket = new WebSocket(wsurl);
socket.onerror = function (e) {
Log("* Connection error");
Log("Connection error");
console.log(e);
};
socket.onopen = function (e) {
@ -329,7 +338,7 @@ function Connect() {
w(MessageNick, nickname);
updateVoiceStatus();
updateUserStatus();
};
socket.onmessage = function (e) {
if (ReconnectDelay > 0) {
@ -355,25 +364,25 @@ function Connect() {
return;
}
Log("* " + escapeEntities(p.N) + " connected");
Log(escapeEntities(p.N) + " connected");
} else if (p.T == MessageJoin) {
if (p.N === undefined) {
return;
}
Log("* " + escapeEntities(p.N) + " joined #lobby voice chat");
Log(escapeEntities(p.N) + " joined #lobby voice chat");
} else if (p.T == MessageQuit) {
if (p.N === undefined) {
return;
}
Log("* " + escapeEntities(p.N) + " quit #lobby voice chat");
Log( escapeEntities(p.N) + " quit #lobby voice chat");
} else if (p.T == MessageDisconnect) {
if (p.N === undefined) {
return;
}
Log("* " + escapeEntities(p.N) + " disconnected");
Log(escapeEntities(p.N) + " disconnected");
} else if (p.T == MessageChat) {
if (p.N === undefined) {
return;
@ -395,8 +404,7 @@ function Connect() {
userListStatus = "Users: " + usersconnected + " - Voice chatting: " + usersvoice;
$("#voiceinactiveright").html(userListStatus);
updateVoiceStatus();
updateUserStatus();
}
} else {
// TODO Binary data
@ -407,7 +415,7 @@ function Connect() {
};
socket.onclose = function (e) {
connected = false;
Log("* Disconnected");
Log("Disconnected");
if (ReconnectDelay < 0 || reconnectTimeout != null) {
return;
}
@ -459,7 +467,7 @@ function StartPTT() {
var sender = peerConnections[0].getSenders()[0];
sender.replaceTrack(audioTrack);
updateVoiceStatus();
updateUserStatus();
}
function StopPTT() {
@ -472,14 +480,14 @@ function StopPTT() {
var sender = peerConnections[0].getSenders()[0];
sender.replaceTrack(null);
updateVoiceStatus();
updateUserStatus();
}
function updateVoiceStatus() {
function updateUserStatus() {
if (ptt) {
$('#voiceactiveleft').html('<b>Transmitting</b>');
$('#userstatus').html('<b>Transmitting</b>');
} else {
$('#voiceactiveleft').html(userListStatus);
$('#userstatus').html(userListStatus);
}
}

107
pkg/web/public/index.html

@ -1,54 +1,75 @@
<!DOCTYPE html>
<html>
<head>
<title>#lobby - harmony</title>
<title>harmony</title>
<link rel="stylesheet" href="assets/css/harmony.css">
<script src="assets/js/jquery.js"></script>
<script src="assets/js/harmony.js"></script>
</head>
<body>
<table style="width: 100%; height: 100%;">
<tr>
<td id="chatcontainer" colspan="2">
<div id="chathistory"></div>
<div id="stats"></div>
</td>
</tr>
<tr id="inputheader">
<td colspan="2">
<hr style="color: #eeeeee;">
</td>
</tr>
<tr style="height: 65px;">
<td id="inputcontainer" colspan="2"><textarea id="chatinput" placeholder="Message #lobby" rows="2"></textarea></td>
</tr>
<tr id="inputfooter">
<td colspan="2">
<hr style="color: #777777;margin: 0; padding: 0;">
</td>
</tr>
<tr id="voicepttcontainer" style="display: none;">
<td colspan="2">
<button id="voiceptt">Push-To-Talk</button>
</td>
</tr>
<tr style="height: 60px;">
<td>
<div id="voiceinactiveleft">
<button id="voiceButtonJoin">Join voice chat</button>
</div>
<div id="voiceactiveleft" style="display: none;"></div>
</td>
<td align="right">
<div id="voiceinactiveright" style="">
&nbsp;
</div>
<div id="voiceactiveright" style="display: none;">
<button id="voiceButtonQuit">Quit voice chat</button>
</div>
</td>
</tr>
</table>
<div class="wrapper">
<nav class="sideleft">
<ul>
<li><a href="">Voice user 1</a></li>
<li><a href="">Voice user 2</a></li>
<li><a href="">Voice user 3</a></li>
</ul>
</nav>
<article class="content" id="chathistory">
</article>
<aside class="sideright">
<ul>
<li><a href="">User 1</a></li>
<li><a href="">User 2</a></li>
<li><a href="">User 3</a></li>
<li><a href="">User 4</a></li>
<li><a href="">User 5</a></li>
</ul>
</aside>
<div class="status">
<div id="userstatus">Loading...</div>
</div>
<footer class="footer">
<table width="100%">
<tr id="inputheader">
<td colspan="2">
<hr style="color: #eeeeee;">
</td>
</tr>
<tr>
<td id="inputcontainer" colspan="2">
<textarea id="chatinput" placeholder="Message #lobby" rows="2"></textarea>
</td>
</tr>
<tr id="inputfooter">
<td colspan="2">
<hr style="color: #777777;">
</td>
</tr>
<tr id="voicepttcontainer" style="display: none;">
<td colspan="2">
<button id="voiceptt">Push-To-Talk</button>
</td>
</tr>
<tr>
<td>
<div id="voiceinactiveleft">
<button id="voiceButtonJoin">Join voice chat</button>
</div>
<div id="voiceactiveleft" style="display: none;"></div>
</td>
<td align="right">
<div id="voiceinactiveright" style="">
&nbsp;
</div>
<div id="voiceactiveright" style="display: none;">
<button id="voiceButtonQuit">Quit voice chat</button>
</div>
</td>
</tr>
</table>
</footer>
</div>
<div style="display: none" id="hidden">
</div>
</body>

Loading…
Cancel
Save