Final version source code
This commit is contained in:
parent
8a8a5c6831
commit
371de2fd83
@ -1,2 +1,3 @@
|
|||||||
# MessagingApp
|
# MessagingApp
|
||||||
|
|
||||||
|
A simple messaging app with a nodejs server and Swing front end
|
BIN
engine.io-client-2.0.0.jar
Normal file
BIN
engine.io-client-2.0.0.jar
Normal file
Binary file not shown.
BIN
json-20090211.jar
Normal file
BIN
json-20090211.jar
Normal file
Binary file not shown.
BIN
messagingapp.jar
Normal file
BIN
messagingapp.jar
Normal file
Binary file not shown.
BIN
okhttp-3.12.12.jar
Normal file
BIN
okhttp-3.12.12.jar
Normal file
Binary file not shown.
BIN
okio-1.15.0.jar
Normal file
BIN
okio-1.15.0.jar
Normal file
Binary file not shown.
179
server.js
Normal file
179
server.js
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
// Express is used for HTTP and URL routing
|
||||||
|
const express = require('express');
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const PORT = process.env.PORT || 5000;
|
||||||
|
|
||||||
|
// Library to generate unique identifiers
|
||||||
|
const { v4: uuidv4 } = require('uuid');
|
||||||
|
const uuid = require('uuid');
|
||||||
|
|
||||||
|
// We need the crypto library for sha512 encryption of passwords in the database
|
||||||
|
var crypto = require("crypto");
|
||||||
|
|
||||||
|
// psql driver
|
||||||
|
const { Pool } = require('pg');
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const http = require('http');
|
||||||
|
const server = http.createServer(app);
|
||||||
|
const io = require('socket.io')(server, {
|
||||||
|
cors: {
|
||||||
|
origin: "*"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
Connects to database on deployed app.
|
||||||
|
*/
|
||||||
|
const pool = new Pool({
|
||||||
|
connectionString: process.env.DATABASE_URL,
|
||||||
|
ssl: {
|
||||||
|
rejectUnauthorized: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
app.use(express.json())
|
||||||
|
app.use(express.urlencoded({
|
||||||
|
extended: true
|
||||||
|
}))
|
||||||
|
|
||||||
|
users = {}
|
||||||
|
|
||||||
|
io.on("connection", (socket) => {
|
||||||
|
socket.emit("hello", {"hello": "world"});
|
||||||
|
socket.on('disconnect', () => {
|
||||||
|
console.log('user disconnected');
|
||||||
|
delete users[socket.id];
|
||||||
|
socket.broadcast.emit('users', getUsers());
|
||||||
|
});
|
||||||
|
socket.on("hello", (arg) => {
|
||||||
|
console.log("hello" + arg); // world
|
||||||
|
});
|
||||||
|
socket.on("message", (arg) => {
|
||||||
|
socket.broadcast.emit('message', arg);
|
||||||
|
saveMessage(users[socket.id], arg);
|
||||||
|
});
|
||||||
|
socket.on("privateMessage", (msg, to) => {
|
||||||
|
var socketID = [];
|
||||||
|
for (user in users){
|
||||||
|
console.log(user);
|
||||||
|
if (users[user].toString() == to.toString()){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log("Private message to " + to + " " + socketID[0]);
|
||||||
|
io.to(socketID[0]).emit('privateMessage', users[socket.id], msg);
|
||||||
|
saveMessage(users[socket.id], users[socketID[0]], msg);
|
||||||
|
});
|
||||||
|
socket.on("login", (data) => {
|
||||||
|
data = data.split(",");
|
||||||
|
var username = data[0];
|
||||||
|
var pw = data[1];
|
||||||
|
pool.query(`SELECT username,password FROM accounts where username='${username}'`, (err, result) => {
|
||||||
|
if (err){
|
||||||
|
error('A critical database error occured while user was attempting to login');
|
||||||
|
socket.emit('logInError', 'A critical database error occured while user was attempting to login');
|
||||||
|
}
|
||||||
|
else if (result.rowCount == 0){
|
||||||
|
socket.emit('logInError', `Invalid credentials`);
|
||||||
|
}
|
||||||
|
else if (result.rows[0].username == username && result.rows[0].password == sha512(pw)){
|
||||||
|
var uhash = sha512(username);
|
||||||
|
socket.emit('users', getUsers());
|
||||||
|
users[socket.id] = username;
|
||||||
|
socket.broadcast.emit('users', getUsers());
|
||||||
|
socket.emit('loggedIn', `${username}`);
|
||||||
|
getMessages();
|
||||||
|
log('User logged in');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
socket.emit('logInError', `Invalid credentials`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
socket.on("register", (data) => {
|
||||||
|
data = data.split(",");
|
||||||
|
var id = uuidv4();
|
||||||
|
var username = data[0];
|
||||||
|
var pw = data[1];
|
||||||
|
pool.query(`SELECT * FROM accounts where username='${username}'`, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
error(err);
|
||||||
|
error('A critical database error occured while user was attempting to create an account');
|
||||||
|
socket.emit('registerError', 'A critical database error occured while user was attempting to create an account');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (result.rowCount == 0){
|
||||||
|
var pwhash = sha512(pw);
|
||||||
|
var uhash = sha512(username);
|
||||||
|
pool.query(`insert into accounts values('${id}', '${username}', '${pwhash}')`, (err, result) => {
|
||||||
|
console.log(err);
|
||||||
|
console.log(result);
|
||||||
|
if (err){
|
||||||
|
socket.emit('registerError', 'A critical database error occured while user was attempting to create an account');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
socket.username = username;
|
||||||
|
socket.emit('registered', `${username}`);
|
||||||
|
log(`${username} registered with ${id}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
socket.emit('registerError', `Username already exists`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
|
function getMessages(){
|
||||||
|
pool.query(`SELECT MESSAGE FROM message where TO_USER='all'`, (err, result) => {
|
||||||
|
//console.log(result.rows);
|
||||||
|
console.log("GETTING MESSAGES");
|
||||||
|
socket.emit('messages', result.rows);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hash password with sha512.
|
||||||
|
* @function
|
||||||
|
* @param {string} password - List of required fields.
|
||||||
|
* @param {string} salt - Data to be validated.
|
||||||
|
*/
|
||||||
|
var sha512 = function(password, salt = "messaging"){
|
||||||
|
var hash = crypto.createHmac('sha512', salt); /** Hashing algorithm sha512 */
|
||||||
|
hash.update(password);
|
||||||
|
var value = hash.digest('hex');
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
server.listen(PORT, function(){ log("Listening on port " + PORT); })
|
||||||
|
|
||||||
|
function getUsers(){
|
||||||
|
u = [];
|
||||||
|
for (user in users){
|
||||||
|
u.push(users[user]);
|
||||||
|
}
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveMessage(from, msg){
|
||||||
|
pool.query(`insert into message values('${from}', 'all', '${msg}')`, (err, result) => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
function savePrivateMessage(from, to, msg){
|
||||||
|
pool.query(`insert into message values('${from}', '${to}', '${msg}')`, (err, result) => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function log(input){
|
||||||
|
console.log(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
function error(input){
|
||||||
|
console.error(input);
|
||||||
|
}
|
BIN
socket.io-client-2.0.0.jar
Normal file
BIN
socket.io-client-2.0.0.jar
Normal file
Binary file not shown.
40
src/App.java
Normal file
40
src/App.java
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import io.socket.client.IO;
|
||||||
|
import io.socket.client.Socket;
|
||||||
|
import io.socket.emitter.Emitter;
|
||||||
|
import io.socket.engineio.client.Transport;
|
||||||
|
import io.socket.engineio.client.transports.Polling;
|
||||||
|
import io.socket.engineio.client.transports.WebSocket;
|
||||||
|
import javafx.application.Application;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
|
public class App extends Application {
|
||||||
|
static Client socket;
|
||||||
|
static String username;
|
||||||
|
static ArrayList<String> activeUsers = new ArrayList<String>();
|
||||||
|
static ArrayList<String> messages = new ArrayList<String>();
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
launch(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(final Stage primaryStage) throws Exception {
|
||||||
|
socket = new Client(primaryStage);
|
||||||
|
primaryStage.setTitle("Messaging app");
|
||||||
|
primaryStage.setResizable(false);
|
||||||
|
primaryStage.setScene(LoginPage.makeLoginPage(primaryStage, socket));
|
||||||
|
primaryStage.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop(){
|
||||||
|
System.out.println("disconnecting");
|
||||||
|
socket.disconnect();
|
||||||
|
}
|
||||||
|
}
|
236
src/Client.java
Normal file
236
src/Client.java
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
import java.net.URI;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import io.socket.client.IO;
|
||||||
|
import io.socket.client.Socket;
|
||||||
|
import io.socket.emitter.Emitter;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
public class Client {
|
||||||
|
Socket socket;
|
||||||
|
Stage primaryStage;
|
||||||
|
Client client;
|
||||||
|
|
||||||
|
public Client(Stage primaryStage) {
|
||||||
|
this.client = this;
|
||||||
|
this.primaryStage = primaryStage;
|
||||||
|
socket = IO.socket(URI.create("http://messagingappsoftwareeng.herokuapp.com"));
|
||||||
|
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void call(Object... args) {
|
||||||
|
System.out.println("Connected to server!");
|
||||||
|
socket.emit("hello", " world");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
socket.on("hello", new Emitter.Listener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void call(Object... args) {
|
||||||
|
JSONObject response = (JSONObject) args[0];
|
||||||
|
try {
|
||||||
|
System.out.println("Hello " + response.getString("hello"));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("users", new Emitter.Listener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void call(Object... args) {
|
||||||
|
System.out.println(args[0]);
|
||||||
|
Platform.runLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
App.activeUsers.clear();
|
||||||
|
JSONArray jsonArray = (JSONArray) args[0];
|
||||||
|
String[] users = toStringArray(jsonArray);
|
||||||
|
if (users != null && users.length > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < users.length; i++) {
|
||||||
|
if (users[i].equals(App.username)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
App.activeUsers.add(users[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MainLobby.updateUsers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("message", new Emitter.Listener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void call(Object... args) {
|
||||||
|
App.messages.add((String) args[0]);
|
||||||
|
MainLobby.updateMessages((String) args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("privateMessage", new Emitter.Listener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void call(Object... args) {
|
||||||
|
System.out.println((String)args[0]);
|
||||||
|
System.out.println((String)args[1]);
|
||||||
|
Platform.runLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
String username = (String) args[0];
|
||||||
|
if (MainLobby.privateMessageWindows.get(username) != null && MainLobby.privateMessageWindows.containsKey(username)) {
|
||||||
|
MainLobby.privateMessageWindows.get(username).show();
|
||||||
|
MainLobby.privateMessageWindows.get(username).updateMessages((String) args[1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MainLobby.privateMessageWindows.put(username, new Conversation(username, client));
|
||||||
|
MainLobby.privateMessageWindows.get(username).updateMessages((String) args[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("messages", new Emitter.Listener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void call(Object... args) {
|
||||||
|
String messages = "";
|
||||||
|
JSONArray msgs = (JSONArray)args[0];
|
||||||
|
for (int i = 0; i < msgs.length(); i++) {
|
||||||
|
try {
|
||||||
|
messages += msgs.optJSONObject(i).getString("message") + "\n";
|
||||||
|
} catch (JSONException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
|
||||||
|
Thread.sleep(2000);
|
||||||
|
}catch(InterruptedException ex){
|
||||||
|
//do stuff
|
||||||
|
}
|
||||||
|
MainLobby.updateMessages(messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("registered", new Emitter.Listener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void call(Object... args) {
|
||||||
|
System.out.println("Registration successful " + args[0]);
|
||||||
|
Platform.runLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
new MessageBox("Registered", "Successfully registered with username '" + (String) args[0]
|
||||||
|
+ "'.\n You can log in now!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("registerError", new Emitter.Listener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void call(Object... args) {
|
||||||
|
System.out.println("Couldn't register: " + args[0]);
|
||||||
|
Platform.runLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
new MessageBox("Register Error", (String) args[0]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("loggedIn", new Emitter.Listener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void call(Object... args) {
|
||||||
|
System.out.println("Login successful " + args[0]);
|
||||||
|
Platform.runLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
App.username = (String) args[0];
|
||||||
|
new MainLobby(primaryStage, client);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("logInError", new Emitter.Listener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void call(Object... args) {
|
||||||
|
System.out.println("Couldn't login: " + args[0]);
|
||||||
|
Platform.runLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
new MessageBox("Login Error", (String) args[0]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
socket.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void register(String username, String password) {
|
||||||
|
socket.emit("register", username + "," + password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void login(String username, String password) {
|
||||||
|
socket.emit("login", username + "," + password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void message(String message) {
|
||||||
|
socket.emit("message", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void privateMessage(String message, String to) {
|
||||||
|
socket.emit("privateMessage", message, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disconnect() {
|
||||||
|
socket.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String[] toStringArray(JSONArray array) {
|
||||||
|
if(array==null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
String[] arr=new String[array.length()];
|
||||||
|
for(int i=0; i<arr.length; i++) {
|
||||||
|
arr[i]=array.optString(i);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
}
|
88
src/Conversation.java
Normal file
88
src/Conversation.java
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.ScrollPane;
|
||||||
|
import javafx.scene.control.TextArea;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
import javafx.scene.text.Font;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.scene.text.TextAlignment;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
public class Conversation {
|
||||||
|
Stage stage;
|
||||||
|
Client client;
|
||||||
|
TextArea messageList;
|
||||||
|
String username;
|
||||||
|
Conversation(String username, Client client)
|
||||||
|
{
|
||||||
|
this.client = client;
|
||||||
|
this.username = username;
|
||||||
|
BorderPane border = new BorderPane();
|
||||||
|
|
||||||
|
Text title = new Text(username);
|
||||||
|
StackPane stack = new StackPane();
|
||||||
|
stack.setPadding(new Insets(15, 12, 15, 12));
|
||||||
|
title.prefWidth(800);
|
||||||
|
title.setTextAlignment(TextAlignment.CENTER);
|
||||||
|
title.setFont(new Font(24));
|
||||||
|
stack.getChildren().add(title);
|
||||||
|
border.setTop(stack);
|
||||||
|
|
||||||
|
HBox hbox = new HBox();
|
||||||
|
hbox.setPadding(new Insets(15, 12, 15, 12));
|
||||||
|
hbox.setSpacing(10);
|
||||||
|
//hbox.setStyle("-fx-background-color: #336699;");
|
||||||
|
|
||||||
|
TextField messageTextField = new TextField();
|
||||||
|
messageTextField.setPrefSize(600, 20);
|
||||||
|
Button buttonCurrent = new Button("Send message");
|
||||||
|
buttonCurrent.setOnAction(new EventHandler<ActionEvent>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(ActionEvent e) {
|
||||||
|
String message = App.username + ": " + messageTextField.getText();
|
||||||
|
client.privateMessage(message, username);
|
||||||
|
messageTextField.setText("");
|
||||||
|
updateMessages(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
buttonCurrent.setPrefSize(200, 20);
|
||||||
|
|
||||||
|
hbox.getChildren().addAll(messageTextField, buttonCurrent);
|
||||||
|
|
||||||
|
border.setBottom(hbox);
|
||||||
|
|
||||||
|
ScrollPane scroll = new ScrollPane();
|
||||||
|
scroll.setFitToHeight(true);
|
||||||
|
scroll.setFitToWidth(true);
|
||||||
|
scroll.setPadding(new Insets(15, 12, 15, 12));
|
||||||
|
messageList = new TextArea();
|
||||||
|
String messages = "";
|
||||||
|
messageList.setText(messages);
|
||||||
|
messageList.setEditable(false);
|
||||||
|
messageList.setWrapText(true);
|
||||||
|
messageList.setPrefSize(525, 500);
|
||||||
|
scroll.setContent(messageList);
|
||||||
|
border.setCenter(scroll);
|
||||||
|
|
||||||
|
stage = new Stage();
|
||||||
|
stage.setResizable(false);
|
||||||
|
stage.setTitle("Conversation | " + username);
|
||||||
|
stage.setScene(new Scene(border, 800, 600));
|
||||||
|
stage.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateMessages(String text) {
|
||||||
|
messageList.appendText(text + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
stage.show();
|
||||||
|
}
|
||||||
|
}
|
79
src/LoginPage.java
Normal file
79
src/LoginPage.java
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.PasswordField;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.text.Font;
|
||||||
|
import javafx.scene.text.FontWeight;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
public class LoginPage {
|
||||||
|
public static Scene makeLoginPage(Stage primaryStage, Client client) {
|
||||||
|
GridPane grid = new GridPane();
|
||||||
|
grid.setAlignment(Pos.CENTER);
|
||||||
|
grid.setHgap(10);
|
||||||
|
grid.setVgap(10);
|
||||||
|
grid.setPadding(new Insets(25, 25, 25, 25));
|
||||||
|
Text scenetitle = new Text("Login");
|
||||||
|
scenetitle.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
|
||||||
|
grid.add(scenetitle, 0, 0, 2, 1);
|
||||||
|
|
||||||
|
Label userName = new Label("User Name:");
|
||||||
|
grid.add(userName, 0, 1);
|
||||||
|
|
||||||
|
TextField userTextField = new TextField();
|
||||||
|
grid.add(userTextField, 1, 1);
|
||||||
|
|
||||||
|
Label pw = new Label("Password:");
|
||||||
|
grid.add(pw, 0, 2);
|
||||||
|
|
||||||
|
PasswordField pwBox = new PasswordField();
|
||||||
|
grid.add(pwBox, 1, 2);
|
||||||
|
|
||||||
|
Button btn = new Button("Register");
|
||||||
|
HBox hbBtn = new HBox(10);
|
||||||
|
hbBtn.setAlignment(Pos.BOTTOM_RIGHT);
|
||||||
|
hbBtn.getChildren().add(btn);
|
||||||
|
grid.add(hbBtn, 0, 4);
|
||||||
|
|
||||||
|
Button btn2 = new Button("Sign in");
|
||||||
|
HBox hbBtn2 = new HBox(10);
|
||||||
|
hbBtn2.setAlignment(Pos.BOTTOM_RIGHT);
|
||||||
|
hbBtn2.getChildren().add(btn2);
|
||||||
|
grid.add(hbBtn2, 1, 4);
|
||||||
|
|
||||||
|
btn.setOnAction(new EventHandler<ActionEvent>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(ActionEvent e) {
|
||||||
|
/* Change the scene of the primaryStage */
|
||||||
|
try {
|
||||||
|
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
// do stuff
|
||||||
|
}
|
||||||
|
primaryStage.close();
|
||||||
|
primaryStage.setScene(RegisterPage.makeRegisterPage(primaryStage, client));
|
||||||
|
primaryStage.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
btn2.setOnAction(new EventHandler<ActionEvent>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(ActionEvent e) {
|
||||||
|
client.login(userTextField.getText(), pwBox.getText());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return new Scene(grid, 400, 400);
|
||||||
|
}
|
||||||
|
}
|
152
src/MainLobby.java
Normal file
152
src/MainLobby.java
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.ListView;
|
||||||
|
import javafx.scene.control.ScrollPane;
|
||||||
|
import javafx.scene.control.TextArea;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.scene.text.Font;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.scene.text.TextAlignment;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
public class MainLobby {
|
||||||
|
static Stage primaryStage;
|
||||||
|
static BorderPane border = new BorderPane();
|
||||||
|
static Scene scene;
|
||||||
|
Client client;
|
||||||
|
static TextArea messageList;
|
||||||
|
static ListView userList;
|
||||||
|
//static HashMap<String, String> privateMessages = new HashMap<String, String>();
|
||||||
|
static HashMap<String, Conversation> privateMessageWindows = new HashMap<String, Conversation>();
|
||||||
|
static Image image;
|
||||||
|
|
||||||
|
MainLobby(Stage primaryStage, Client client) {
|
||||||
|
this.client = client;
|
||||||
|
primaryStage.close();
|
||||||
|
primaryStage.setTitle("Main Lobby");
|
||||||
|
|
||||||
|
//Text lobbytitle = new Text("Lobby");
|
||||||
|
try {
|
||||||
|
image = new Image(new FileInputStream("Officon_Logo.png"));
|
||||||
|
} catch (FileNotFoundException e1) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
|
ImageView imageView = new ImageView(image);
|
||||||
|
//Setting the preserve ratio of the image view
|
||||||
|
imageView.setPreserveRatio(true);
|
||||||
|
imageView.setFitHeight(46);
|
||||||
|
StackPane stack = new StackPane();
|
||||||
|
stack.setPadding(new Insets(15, 12, 15, 12));
|
||||||
|
//lobbytitle.prefWidth(800);
|
||||||
|
//lobbytitle.setTextAlignment(TextAlignment.CENTER);
|
||||||
|
//lobbytitle.setFont(new Font(20));
|
||||||
|
stack.getChildren().add(imageView);
|
||||||
|
border.setTop(stack);
|
||||||
|
|
||||||
|
VBox vbox = new VBox();
|
||||||
|
vbox.setPadding(new Insets(15, 12, 15, 12));
|
||||||
|
Text listtitle = new Text("Online users");
|
||||||
|
StackPane liststack = new StackPane();
|
||||||
|
liststack.setPadding(new Insets(15, 12, 15, 12));
|
||||||
|
liststack.getChildren().add(listtitle);
|
||||||
|
userList = new ListView();
|
||||||
|
for (String user : App.activeUsers) {
|
||||||
|
userList.getItems().add(user);
|
||||||
|
}
|
||||||
|
userList.setPrefHeight(600);
|
||||||
|
|
||||||
|
Button button = new Button("Message User");
|
||||||
|
button.setOnAction(new EventHandler<ActionEvent>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(ActionEvent e) {
|
||||||
|
String username = (String) userList.getSelectionModel().getSelectedItem();
|
||||||
|
if (privateMessageWindows.get(username) != null && privateMessageWindows.containsKey(username)) {
|
||||||
|
privateMessageWindows.get(username).show();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
privateMessageWindows.put(username, new Conversation(username, client));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
button.setPrefWidth(250);
|
||||||
|
vbox.getChildren().addAll(liststack, userList, button);
|
||||||
|
border.setLeft(vbox);
|
||||||
|
|
||||||
|
HBox hbox = new HBox();
|
||||||
|
hbox.setPadding(new Insets(15, 12, 15, 12));
|
||||||
|
hbox.setSpacing(10);
|
||||||
|
// hbox.setStyle("-fx-background-color: #336699;");
|
||||||
|
|
||||||
|
TextField messageTextField = new TextField();
|
||||||
|
messageTextField.setText("");
|
||||||
|
messageTextField.setPrefSize(600, 20);
|
||||||
|
Button buttonCurrent = new Button("Send message");
|
||||||
|
buttonCurrent.setPrefSize(200, 20);
|
||||||
|
buttonCurrent.setOnAction(new EventHandler<ActionEvent>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(ActionEvent e) {
|
||||||
|
String message = App.username + ": " + messageTextField.getText();
|
||||||
|
client.message(message);
|
||||||
|
App.messages.add(message);
|
||||||
|
messageTextField.setText("");
|
||||||
|
updateMessages(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
hbox.getChildren().addAll(messageTextField, buttonCurrent);
|
||||||
|
|
||||||
|
border.setBottom(hbox);
|
||||||
|
|
||||||
|
ScrollPane scroll = new ScrollPane();
|
||||||
|
scroll.setFitToHeight(true);
|
||||||
|
scroll.setFitToWidth(true);
|
||||||
|
scroll.setPadding(new Insets(15, 12, 15, 12));
|
||||||
|
messageList = new TextArea();
|
||||||
|
String messages = "";
|
||||||
|
if (App.messages != null) {
|
||||||
|
for (String message: App.messages) {
|
||||||
|
messages += message +"\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
messageList.setText(messages);
|
||||||
|
messageList.setEditable(false);
|
||||||
|
messageList.setWrapText(true);
|
||||||
|
messageList.setPrefSize(525, 500);
|
||||||
|
scroll.setContent(messageList);
|
||||||
|
border.setCenter(scroll);
|
||||||
|
|
||||||
|
|
||||||
|
scene = new Scene(border, 800, 600);
|
||||||
|
primaryStage.setScene(scene);
|
||||||
|
primaryStage.show();
|
||||||
|
this.primaryStage = primaryStage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateUsers() {
|
||||||
|
for (String user : App.activeUsers) {
|
||||||
|
userList.getItems().add(user);
|
||||||
|
}
|
||||||
|
userList.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateMessages(String text) {
|
||||||
|
messageList.appendText(text + "\n");
|
||||||
|
}
|
||||||
|
}
|
52
src/MessageBox.java
Normal file
52
src/MessageBox.java
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.text.Font;
|
||||||
|
import javafx.scene.text.FontWeight;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
public class MessageBox {
|
||||||
|
MessageBox(String title, String message){
|
||||||
|
BorderPane border = new BorderPane();
|
||||||
|
|
||||||
|
StackPane stack = new StackPane();
|
||||||
|
|
||||||
|
Text msg = new Text(message);
|
||||||
|
//msg.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
|
||||||
|
stack.getChildren().add(msg);
|
||||||
|
|
||||||
|
|
||||||
|
StackPane bstack = new StackPane();
|
||||||
|
bstack.setPadding(new Insets(0, 12, 30, 12));
|
||||||
|
|
||||||
|
Button btn = new Button("OK");
|
||||||
|
|
||||||
|
btn.setOnAction(new EventHandler<ActionEvent>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(ActionEvent e) {
|
||||||
|
Stage stage = (Stage) btn.getScene().getWindow();
|
||||||
|
stage.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
bstack.getChildren().add(btn);
|
||||||
|
|
||||||
|
border.setCenter(stack);
|
||||||
|
border.setBottom(bstack);
|
||||||
|
|
||||||
|
Stage stage = new Stage();
|
||||||
|
stage.setTitle(title);
|
||||||
|
stage.setScene(new Scene(border, 300, 100));
|
||||||
|
stage.setResizable(false);
|
||||||
|
stage.setAlwaysOnTop(true);
|
||||||
|
stage.show();
|
||||||
|
}
|
||||||
|
}
|
92
src/RegisterPage.java
Normal file
92
src/RegisterPage.java
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.PasswordField;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.text.Font;
|
||||||
|
import javafx.scene.text.FontWeight;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
public class RegisterPage {
|
||||||
|
public static Scene makeRegisterPage(Stage primaryStage, Client client) {
|
||||||
|
GridPane grid = new GridPane();
|
||||||
|
grid.setAlignment(Pos.CENTER);
|
||||||
|
grid.setHgap(10);
|
||||||
|
grid.setVgap(10);
|
||||||
|
grid.setPadding(new Insets(25, 25, 25, 25));
|
||||||
|
Text scenetitle = new Text("Register");
|
||||||
|
scenetitle.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
|
||||||
|
grid.add(scenetitle, 0, 0, 2, 1);
|
||||||
|
|
||||||
|
Label userName = new Label("User Name:");
|
||||||
|
grid.add(userName, 0, 1);
|
||||||
|
|
||||||
|
TextField userTextField = new TextField();
|
||||||
|
grid.add(userTextField, 1, 1);
|
||||||
|
|
||||||
|
Label pw = new Label("Password:");
|
||||||
|
grid.add(pw, 0, 2);
|
||||||
|
|
||||||
|
PasswordField pwBox = new PasswordField();
|
||||||
|
grid.add(pwBox, 1, 2);
|
||||||
|
|
||||||
|
Label cpw = new Label("Confirm password:");
|
||||||
|
grid.add(cpw, 0, 3);
|
||||||
|
|
||||||
|
PasswordField cpwBox = new PasswordField();
|
||||||
|
grid.add(cpwBox, 1, 3);
|
||||||
|
|
||||||
|
Button btn = new Button("Register");
|
||||||
|
HBox hbBtn = new HBox(25);
|
||||||
|
hbBtn.setAlignment(Pos.BOTTOM_RIGHT);
|
||||||
|
hbBtn.getChildren().add(btn);
|
||||||
|
grid.add(hbBtn, 1, 5);
|
||||||
|
|
||||||
|
Button btn2 = new Button("Back");
|
||||||
|
HBox hbBtn2 = new HBox(10);
|
||||||
|
hbBtn2.setAlignment(Pos.BOTTOM_LEFT);
|
||||||
|
hbBtn2.getChildren().add(btn2);
|
||||||
|
grid.add(hbBtn2, 0, 5);
|
||||||
|
|
||||||
|
final Text actiontarget = new Text();
|
||||||
|
grid.add(actiontarget, 1, 6);
|
||||||
|
|
||||||
|
btn.setOnAction(new EventHandler<ActionEvent>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(ActionEvent e) {
|
||||||
|
actiontarget.setFill(Color.FIREBRICK);
|
||||||
|
if (pwBox.getText().equals(cpwBox.getText())) {
|
||||||
|
client.register(userTextField.getText(), pwBox.getText());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
new MessageBox("Register Error", "Password fields don't match");
|
||||||
|
cpwBox.setText("");
|
||||||
|
pwBox.setText("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
btn2.setOnAction(new EventHandler<ActionEvent>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(ActionEvent e) {
|
||||||
|
primaryStage.close();
|
||||||
|
primaryStage.setScene(LoginPage.makeLoginPage(primaryStage, client));
|
||||||
|
primaryStage.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return new Scene(grid, 400, 400);
|
||||||
|
}
|
||||||
|
}
|
3
tables.sql
Normal file
3
tables.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
CREATE TABLE ACCOUNTS (ACCOUNT_ID TEXT PRIMARY KEY NOT NULL, USERNAME TEXT NOT NULL, PASSWORD TEXT NOT NULL);
|
||||||
|
|
||||||
|
CREATE TABLE MESSAGE (FROM_USER TEXT NOT NULL, TO_USER TEXT NOT NULL, MESSAGE TEXT);
|
Loading…
x
Reference in New Issue
Block a user