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 lingo.client.api.StompTopics;
import lingo.common.ChatMessage;
import lingo.common.Game;
import lingo.common.Report;
@ -49,6 +50,12 @@ public class LingoController implements ApplicationListener<AbstractSubProtocolE
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")
public void guess(String guess, @Header(SESSION_ID_HEADER) String sessionId) {
guess = guess.toUpperCase();

View File

@ -16,3 +16,23 @@ h1 {
.hidden {
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">
</head>
<body>
<div id="usernameDiv" class="container">
<div class="jumbotron">
<p>Choose your username.<p>
<form>
<div class="form-group">
<input id="username" type="text" class="form-control" maxlength="16" placeholder="Username">
</div>
<button id="usernameButton" type="button" class="btn btn-default">Go</button>
</form>
<div class="container">
<div id="usernameDiv">
<div class="jumbotron">
<p>Choose your username.<p>
<form>
<div class="form-group">
<input id="username" type="text" class="form-control" maxlength="16" placeholder="Username">
</div>
<button id="usernameButton" type="button" class="btn btn-default">Go</button>
</form>
</div>
</div>
</div>
<div id="canvasDiv" class="hidden">
<canvas id="canvas" width="600" height="475"></canvas>
</div>
<div id="waitingDiv" class="hidden">
<h1>Waiting for Opponent</h1>
<!-- Based on http://tobiasahlin.com/spinkit -->
<div class="sk-cube-grid">
<div class="sk-cube sk-cube1"></div>
<div class="sk-cube sk-cube2"></div>
<div class="sk-cube sk-cube3"></div>
<div class="sk-cube sk-cube4"></div>
<div class="sk-cube sk-cube5"></div>
<div class="sk-cube sk-cube6"></div>
<div class="sk-cube sk-cube7"></div>
<div class="sk-cube sk-cube8"></div>
<div class="sk-cube sk-cube9"></div>
<div class="sk-cube sk-cube10"></div>
<div class="sk-cube sk-cube11"></div>
<div class="sk-cube sk-cube12"></div>
<div class="sk-cube sk-cube13"></div>
<div class="sk-cube sk-cube14"></div>
<div class="sk-cube sk-cube15"></div>
<div class="sk-cube sk-cube16"></div>
<div class="sk-cube sk-cube17"></div>
<div class="sk-cube sk-cube18"></div>
<div class="sk-cube sk-cube19"></div>
<div class="sk-cube sk-cube20"></div>
<div class="sk-cube sk-cube21"></div>
<div class="sk-cube sk-cube22"></div>
<div class="sk-cube sk-cube23"></div>
<div class="sk-cube sk-cube24"></div>
<div class="sk-cube sk-cube25"></div>
<div class="sk-cube sk-cube26"></div>
<div class="sk-cube sk-cube27"></div>
<div class="sk-cube sk-cube28"></div>
<div class="sk-cube sk-cube29"></div>
<div class="sk-cube sk-cube30"></div>
<div id="canvasDiv" class="hidden">
<canvas id="canvas" width="600" height="475" tabindex="1"></canvas>
</div>
<div id="waitingDiv" class="hidden">
<h1>Waiting for Opponent</h1>
<!-- Based on http://tobiasahlin.com/spinkit -->
<div class="sk-cube-grid">
<div class="sk-cube sk-cube1"></div>
<div class="sk-cube sk-cube2"></div>
<div class="sk-cube sk-cube3"></div>
<div class="sk-cube sk-cube4"></div>
<div class="sk-cube sk-cube5"></div>
<div class="sk-cube sk-cube6"></div>
<div class="sk-cube sk-cube7"></div>
<div class="sk-cube sk-cube8"></div>
<div class="sk-cube sk-cube9"></div>
<div class="sk-cube sk-cube10"></div>
<div class="sk-cube sk-cube11"></div>
<div class="sk-cube sk-cube12"></div>
<div class="sk-cube sk-cube13"></div>
<div class="sk-cube sk-cube14"></div>
<div class="sk-cube sk-cube15"></div>
<div class="sk-cube sk-cube16"></div>
<div class="sk-cube sk-cube17"></div>
<div class="sk-cube sk-cube18"></div>
<div class="sk-cube sk-cube19"></div>
<div class="sk-cube sk-cube20"></div>
<div class="sk-cube sk-cube21"></div>
<div class="sk-cube sk-cube22"></div>
<div class="sk-cube sk-cube23"></div>
<div class="sk-cube sk-cube24"></div>
<div class="sk-cube sk-cube25"></div>
<div class="sk-cube sk-cube26"></div>
<div class="sk-cube sk-cube27"></div>
<div class="sk-cube sk-cube28"></div>
<div class="sk-cube sk-cube29"></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>

View File

@ -1,3 +1,6 @@
var KEYCODE_BACKSPACE = 8;
var KEYCODE_RETURN = 13;
var HEIGHT = 300;
var WIDTH = 250;
var SIDE = 50;
@ -15,15 +18,16 @@ var opponentResults;
var opponentUsername;
var lastWord;
var usernameDiv = document.getElementById('usernameDiv');
var canvasDiv = document.getElementById('canvasDiv');
var waitingDiv = document.getElementById('waitingDiv');
var messageDiv = document.getElementById('messageDiv');
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var client;
function main() {
var usernameDiv = document.getElementById('usernameDiv');
var submitUsernameFunction = function() {
myUsername = usernameInput.value;
localStorage.setItem('lingo.username', myUsername);
@ -31,13 +35,14 @@ function main() {
start();
usernameDiv.classList.add('hidden');
waitingDiv.classList.remove('hidden');
messageDiv.classList.remove('hidden');
}
var usernameInput = document.getElementById('username');
var usernameButton = document.getElementById('usernameButton');
usernameButton.addEventListener('click', submitUsernameFunction);
usernameInput.focus();
usernameInput.addEventListener('keydown', function(e) {
if (e.keyCode === 13) {
if (e.keyCode === KEYCODE_RETURN) {
e.preventDefault();
submitUsernameFunction();
}
@ -57,6 +62,7 @@ function start() {
addKeydownListener();
addKeypressListener();
addChatMessageListener();
reset();
repaint();
@ -64,6 +70,7 @@ function start() {
client = Stomp.over(new SockJS('/stomp'));
client.connect({}, function(frame) {
subscribeToChatMessages();
subscribeToOpponentJoined();
subscribeToOpponentLeft();
subscribeToOpponentReports();
@ -74,15 +81,13 @@ function start() {
// special keys
function addKeydownListener() {
document.addEventListener('keydown', function(e) {
// backspace
if (e.which === 8) {
canvasDiv.addEventListener('keydown', function(e) {
if (e.which === KEYCODE_BACKSPACE) {
myGuess = myGuess.substr(0, myGuess.length - 1);
repaint();
e.preventDefault();
}
// return
else if (e.which === 13) {
else if (e.which === KEYCODE_RETURN) {
if (myGuess.length === 5) {
client.send("/app/lingo/guess", {}, myGuess);
myGuess = '';
@ -94,7 +99,7 @@ function addKeydownListener() {
// characters
function addKeypressListener() {
document.addEventListener('keypress', function(e) {
canvasDiv.addEventListener('keypress', function(e) {
var charCode = e.charCode;
if (isCharacter(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() {
var x = 25, y = MARGIN_TOP;
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() {
client.subscribe('/user/topic/lingo/opponentJoined', function(message) {
var report = JSON.parse(message.body);