Add basic chat box

This commit is contained in:
Charles Gould 2017-01-04 17:57:49 -05:00
parent c6ddb46ad3
commit 7e39b17046
5 changed files with 177 additions and 55 deletions

View File

@ -0,0 +1,32 @@
package lingo.common;
public class ChatMessage {
private String username;
private String message;
public ChatMessage() {}
public ChatMessage(String username, String message) {
this.username = username;
this.message = message;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@ -26,6 +26,7 @@ import org.springframework.web.socket.messaging.SessionConnectedEvent;
import org.springframework.web.socket.messaging.SessionDisconnectEvent; import org.springframework.web.socket.messaging.SessionDisconnectEvent;
import lingo.client.api.StompTopics; import lingo.client.api.StompTopics;
import lingo.common.ChatMessage;
import lingo.common.Game; import lingo.common.Game;
import lingo.common.Report; import lingo.common.Report;
@ -49,6 +50,12 @@ public class LingoController implements ApplicationListener<AbstractSubProtocolE
private final Map<String, String> usernameBySession = new HashMap<>(); private final Map<String, String> usernameBySession = new HashMap<>();
@MessageMapping("/chat")
public ChatMessage chat(String message, @Header(SESSION_ID_HEADER) String sessionId) {
final String username = usernameBySession.get(sessionId);
return new ChatMessage(username, message);
}
@MessageMapping("/guess") @MessageMapping("/guess")
public void guess(String guess, @Header(SESSION_ID_HEADER) String sessionId) { public void guess(String guess, @Header(SESSION_ID_HEADER) String sessionId) {
guess = guess.toUpperCase(); guess = guess.toUpperCase();

View File

@ -16,3 +16,23 @@ h1 {
.hidden { .hidden {
display: none; display: none;
} }
#canvasDiv {
padding-bottom: 20px;
}
#waitingDiv {
height: 360px;
}
#messageList {
height: 300px;
overflow-y: scroll;
padding: 10px 20px 10px 20px;
}
#messageInput {
width: 100%;
height: 42px;
padding-left: 10px;
}

View File

@ -8,54 +8,73 @@
<link rel="stylesheet" href="cube-grid.css"> <link rel="stylesheet" href="cube-grid.css">
</head> </head>
<body> <body>
<div id="usernameDiv" class="container"> <div class="container">
<div class="jumbotron"> <div id="usernameDiv">
<p>Choose your username.<p> <div class="jumbotron">
<form> <p>Choose your username.<p>
<div class="form-group"> <form>
<input id="username" type="text" class="form-control" maxlength="16" placeholder="Username"> <div class="form-group">
</div> <input id="username" type="text" class="form-control" maxlength="16" placeholder="Username">
<button id="usernameButton" type="button" class="btn btn-default">Go</button> </div>
</form> <button id="usernameButton" type="button" class="btn btn-default">Go</button>
</form>
</div>
</div> </div>
</div> <div id="canvasDiv" class="hidden">
<div id="canvasDiv" class="hidden"> <canvas id="canvas" width="600" height="475" tabindex="1"></canvas>
<canvas id="canvas" width="600" height="475"></canvas> </div>
</div> <div id="waitingDiv" class="hidden">
<div id="waitingDiv" class="hidden"> <h1>Waiting for Opponent</h1>
<h1>Waiting for Opponent</h1> <!-- Based on http://tobiasahlin.com/spinkit -->
<!-- Based on http://tobiasahlin.com/spinkit --> <div class="sk-cube-grid">
<div class="sk-cube-grid"> <div class="sk-cube sk-cube1"></div>
<div class="sk-cube sk-cube1"></div> <div class="sk-cube sk-cube2"></div>
<div class="sk-cube sk-cube2"></div> <div class="sk-cube sk-cube3"></div>
<div class="sk-cube sk-cube3"></div> <div class="sk-cube sk-cube4"></div>
<div class="sk-cube sk-cube4"></div> <div class="sk-cube sk-cube5"></div>
<div class="sk-cube sk-cube5"></div> <div class="sk-cube sk-cube6"></div>
<div class="sk-cube sk-cube6"></div> <div class="sk-cube sk-cube7"></div>
<div class="sk-cube sk-cube7"></div> <div class="sk-cube sk-cube8"></div>
<div class="sk-cube sk-cube8"></div> <div class="sk-cube sk-cube9"></div>
<div class="sk-cube sk-cube9"></div> <div class="sk-cube sk-cube10"></div>
<div class="sk-cube sk-cube10"></div> <div class="sk-cube sk-cube11"></div>
<div class="sk-cube sk-cube11"></div> <div class="sk-cube sk-cube12"></div>
<div class="sk-cube sk-cube12"></div> <div class="sk-cube sk-cube13"></div>
<div class="sk-cube sk-cube13"></div> <div class="sk-cube sk-cube14"></div>
<div class="sk-cube sk-cube14"></div> <div class="sk-cube sk-cube15"></div>
<div class="sk-cube sk-cube15"></div> <div class="sk-cube sk-cube16"></div>
<div class="sk-cube sk-cube16"></div> <div class="sk-cube sk-cube17"></div>
<div class="sk-cube sk-cube17"></div> <div class="sk-cube sk-cube18"></div>
<div class="sk-cube sk-cube18"></div> <div class="sk-cube sk-cube19"></div>
<div class="sk-cube sk-cube19"></div> <div class="sk-cube sk-cube20"></div>
<div class="sk-cube sk-cube20"></div> <div class="sk-cube sk-cube21"></div>
<div class="sk-cube sk-cube21"></div> <div class="sk-cube sk-cube22"></div>
<div class="sk-cube sk-cube22"></div> <div class="sk-cube sk-cube23"></div>
<div class="sk-cube sk-cube23"></div> <div class="sk-cube sk-cube24"></div>
<div class="sk-cube sk-cube24"></div> <div class="sk-cube sk-cube25"></div>
<div class="sk-cube sk-cube25"></div> <div class="sk-cube sk-cube26"></div>
<div class="sk-cube sk-cube26"></div> <div class="sk-cube sk-cube27"></div>
<div class="sk-cube sk-cube27"></div> <div class="sk-cube sk-cube28"></div>
<div class="sk-cube sk-cube28"></div> <div class="sk-cube sk-cube29"></div>
<div class="sk-cube sk-cube29"></div> <div class="sk-cube sk-cube30"></div>
<div class="sk-cube sk-cube30"></div> </div>
</div>
<div id="messageDiv" class="hidden panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Chat</h3>
</div>
<div id="messageList" class="list-group">
<!-- <div class="list-group-item"> -->
<!-- <strong>Laura</strong> Cat gifs are the beeeestt -->
<!-- </div> -->
<!-- <div class="list-group-item"> -->
<!-- <strong>Krista</strong> STFU all of you -->
<!-- </div> -->
<!-- <div class="list-group-item"> -->
<!-- <strong>Colter</strong> Tee hee -->
<!-- </div> -->
</div>
<input id="messageInput" placeholder="Type here..." />
</div> </div>
</div> </div>

View File

@ -1,3 +1,6 @@
var KEYCODE_BACKSPACE = 8;
var KEYCODE_RETURN = 13;
var HEIGHT = 300; var HEIGHT = 300;
var WIDTH = 250; var WIDTH = 250;
var SIDE = 50; var SIDE = 50;
@ -15,15 +18,16 @@ var opponentResults;
var opponentUsername; var opponentUsername;
var lastWord; var lastWord;
var usernameDiv = document.getElementById('usernameDiv');
var canvasDiv = document.getElementById('canvasDiv'); var canvasDiv = document.getElementById('canvasDiv');
var waitingDiv = document.getElementById('waitingDiv'); var waitingDiv = document.getElementById('waitingDiv');
var messageDiv = document.getElementById('messageDiv');
var canvas = document.getElementById('canvas'); var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d'); var ctx = canvas.getContext('2d');
var client; var client;
function main() { function main() {
var usernameDiv = document.getElementById('usernameDiv');
var submitUsernameFunction = function() { var submitUsernameFunction = function() {
myUsername = usernameInput.value; myUsername = usernameInput.value;
localStorage.setItem('lingo.username', myUsername); localStorage.setItem('lingo.username', myUsername);
@ -31,13 +35,14 @@ function main() {
start(); start();
usernameDiv.classList.add('hidden'); usernameDiv.classList.add('hidden');
waitingDiv.classList.remove('hidden'); waitingDiv.classList.remove('hidden');
messageDiv.classList.remove('hidden');
} }
var usernameInput = document.getElementById('username'); var usernameInput = document.getElementById('username');
var usernameButton = document.getElementById('usernameButton'); var usernameButton = document.getElementById('usernameButton');
usernameButton.addEventListener('click', submitUsernameFunction); usernameButton.addEventListener('click', submitUsernameFunction);
usernameInput.focus(); usernameInput.focus();
usernameInput.addEventListener('keydown', function(e) { usernameInput.addEventListener('keydown', function(e) {
if (e.keyCode === 13) { if (e.keyCode === KEYCODE_RETURN) {
e.preventDefault(); e.preventDefault();
submitUsernameFunction(); submitUsernameFunction();
} }
@ -57,6 +62,7 @@ function start() {
addKeydownListener(); addKeydownListener();
addKeypressListener(); addKeypressListener();
addChatMessageListener();
reset(); reset();
repaint(); repaint();
@ -64,6 +70,7 @@ function start() {
client = Stomp.over(new SockJS('/stomp')); client = Stomp.over(new SockJS('/stomp'));
client.connect({}, function(frame) { client.connect({}, function(frame) {
subscribeToChatMessages();
subscribeToOpponentJoined(); subscribeToOpponentJoined();
subscribeToOpponentLeft(); subscribeToOpponentLeft();
subscribeToOpponentReports(); subscribeToOpponentReports();
@ -74,15 +81,13 @@ function start() {
// special keys // special keys
function addKeydownListener() { function addKeydownListener() {
document.addEventListener('keydown', function(e) { canvasDiv.addEventListener('keydown', function(e) {
// backspace if (e.which === KEYCODE_BACKSPACE) {
if (e.which === 8) {
myGuess = myGuess.substr(0, myGuess.length - 1); myGuess = myGuess.substr(0, myGuess.length - 1);
repaint(); repaint();
e.preventDefault(); e.preventDefault();
} }
// return else if (e.which === KEYCODE_RETURN) {
else if (e.which === 13) {
if (myGuess.length === 5) { if (myGuess.length === 5) {
client.send("/app/lingo/guess", {}, myGuess); client.send("/app/lingo/guess", {}, myGuess);
myGuess = ''; myGuess = '';
@ -94,7 +99,7 @@ function addKeydownListener() {
// characters // characters
function addKeypressListener() { function addKeypressListener() {
document.addEventListener('keypress', function(e) { canvasDiv.addEventListener('keypress', function(e) {
var charCode = e.charCode; var charCode = e.charCode;
if (isCharacter(charCode)) { if (isCharacter(charCode)) {
if (isCharacterLowercase(charCode)) { if (isCharacterLowercase(charCode)) {
@ -109,6 +114,31 @@ function addKeypressListener() {
}); });
} }
function addChatMessageListener() {
var messageInput = document.getElementById('messageInput');
messageInput.addEventListener('keydown', function(e) {
if (e.which === KEYCODE_RETURN) {
var text = messageInput.value;
messageInput.value = '';
client.send('/app/lingo/chat', {}, text);
addChatMessage('Me', text);
}
});
}
function addChatMessage(sender, body) {
var messageList = document.getElementById('messageList');
var usernameNode = document.createElement('strong');
var usernameTextNode = document.createTextNode(sender)
usernameNode.appendChild(usernameTextNode);
var messageTextNode = document.createTextNode(' ' + body);
var chatMessage = document.createElement('div');
chatMessage.setAttribute('class', 'list-group-item');
chatMessage.appendChild(usernameNode);
chatMessage.appendChild(messageTextNode);
messageList.appendChild(chatMessage);
}
function drawMyBoard() { function drawMyBoard() {
var x = 25, y = MARGIN_TOP; var x = 25, y = MARGIN_TOP;
drawUsername(x, y, myUsername); drawUsername(x, y, myUsername);
@ -273,6 +303,20 @@ function reset(firstLetter, clearScore) {
} }
} }
function subscribeToChatMessages() {
client.subscribe('/topic/lingo/chat', function(message) {
var chatMessage = JSON.parse(message.body);
var messageSender = chatMessage.username;
var messageBody = chatMessage.message;
if (messageSender === myUsername) {
console.log('Ignoring message sent by myself')
} else {
console.log('Message from ' + messageSender + ": " + messageBody);
addChatMessage(messageSender, messageBody);
}
});
}
function subscribeToOpponentJoined() { function subscribeToOpponentJoined() {
client.subscribe('/user/topic/lingo/opponentJoined', function(message) { client.subscribe('/user/topic/lingo/opponentJoined', function(message) {
var report = JSON.parse(message.body); var report = JSON.parse(message.body);