Add whisper chat option #279
@@ -3,10 +3,12 @@ package ch.unibas.dmi.dbis.cs108.casono.client.chat;
|
|||||||
import ch.unibas.dmi.dbis.cs108.casono.client.network.ChatClient;
|
import ch.unibas.dmi.dbis.cs108.casono.client.network.ChatClient;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
|
import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui.ChatBoxController;
|
import ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui.ChatBoxController;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.*;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.RequestParameter;
|
import java.util.Map;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
@@ -43,9 +45,10 @@ public class ChatController {
|
|||||||
|
|
||||||
private static final long REFRESH_TIME = 1000;
|
private static final long REFRESH_TIME = 1000;
|
||||||
|
|
||||||
private List<String> localUserList;
|
/** List of all users connected to the server, to safe them locally on the client */
|
||||||
|
private final List<String> localUserList;
|
||||||
|
|
||||||
private Logger logger;
|
private final Logger logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor, adds TimerTask to be sent to the server regularly
|
* Constructor, adds TimerTask to be sent to the server regularly
|
||||||
@@ -74,7 +77,7 @@ public class ChatController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to be activated, if a lobby has be chosen. It will update the UI and add a new
|
* Method to be activated, if a lobby has been chosen. It will update the UI and add a new
|
||||||
* ChatModel to hold the Data for the Lobby Chat
|
* ChatModel to hold the Data for the Lobby Chat
|
||||||
*
|
*
|
||||||
* @param lobbyId
|
* @param lobbyId
|
||||||
@@ -86,7 +89,15 @@ public class ChatController {
|
|||||||
this.chatBoxController.addChatTab("Lobby", lobbyChatModel);
|
this.chatBoxController.addChatTab("Lobby", lobbyChatModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** method to get all messages from the server */
|
/**
|
||||||
|
* Method to process the Messages that got polled by the {@link ChatClient}.
|
||||||
|
*
|
||||||
|
* <p>Case distinction for every message: - Messages identified with ChatType.LOBBY -> check if
|
||||||
|
* they belong to the users lobby. - Messages identified with ChatType.GLOBAL -> check if the
|
||||||
|
* target user of that Message is the user, or the message got sent by the user.
|
||||||
|
*
|
||||||
|
* <p>All Messages get added to a particular {@link ChatModel}, if the checks passed.
|
||||||
|
*/
|
||||||
public void receiveMessage() {
|
public void receiveMessage() {
|
||||||
List<Message> newMessages = chatClient.getMessages();
|
List<Message> newMessages = chatClient.getMessages();
|
||||||
if (!newMessages.isEmpty()) {
|
if (!newMessages.isEmpty()) {
|
||||||
@@ -118,11 +129,14 @@ public class ChatController {
|
|||||||
key = new ChatKey(ChatType.WHISPER, msg.target);
|
key = new ChatKey(ChatType.WHISPER, msg.target);
|
||||||
}
|
}
|
||||||
if (chatModelMap.containsKey(key)) {
|
if (chatModelMap.containsKey(key)) {
|
||||||
chatModelMap
|
chatModelMap.get(key).addMessage(msg);
|
||||||
.get(key)
|
|
||||||
.addMessage(msg);
|
|
||||||
} else {
|
} else {
|
||||||
ChatModel chatModel = new ChatModel(ChatType.WHISPER, username, lobbyId, key.targetUser());
|
ChatModel chatModel =
|
||||||
|
new ChatModel(
|
||||||
|
ChatType.WHISPER,
|
||||||
|
username,
|
||||||
|
lobbyId,
|
||||||
|
key.targetUser());
|
||||||
chatBoxController.addWhisperChat(key.targetUser(), chatModel);
|
chatBoxController.addWhisperChat(key.targetUser(), chatModel);
|
||||||
chatModel.addMessage(msg);
|
chatModel.addMessage(msg);
|
||||||
}
|
}
|
||||||
@@ -133,6 +147,14 @@ public class ChatController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to process the usernames of other users connected to the server, after they got polled
|
||||||
|
* by the {@link ChatClient}.
|
||||||
|
*
|
||||||
|
* <p>Checks for every one of the usernames, if it is already in the list localUserList and if
|
||||||
|
* not adds them. For every new User added in the List, they get added as an option to start a
|
||||||
|
* Whisper Chat with.
|
||||||
|
*/
|
||||||
public synchronized void checkWhisperUsers() {
|
public synchronized void checkWhisperUsers() {
|
||||||
List<String> users = chatClient.getUsers();
|
List<String> users = chatClient.getUsers();
|
||||||
logger.info(users);
|
logger.info(users);
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ package ch.unibas.dmi.dbis.cs108.casono.client.network;
|
|||||||
|
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message;
|
import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.RequestParameter;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.RequestParameter;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
@@ -71,6 +70,12 @@ public class ChatClient {
|
|||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to poll the usernames of all users currently connected to the server, by sending the
|
||||||
|
* "LIST_USERS" command.
|
||||||
|
*
|
||||||
|
* @return List of all usernames retrieved from the server.
|
||||||
|
*/
|
||||||
public List<String> getUsers() {
|
public List<String> getUsers() {
|
||||||
logger.info("Asking server for list of users");
|
logger.info("Asking server for list of users");
|
||||||
List<String> users = clientService.processCommand("LIST_USERS");
|
List<String> users = clientService.processCommand("LIST_USERS");
|
||||||
|
|||||||
+23
-8
@@ -11,13 +11,14 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.MenuButton;
|
||||||
|
import javafx.scene.control.MenuItem;
|
||||||
|
import javafx.scene.control.Tab;
|
||||||
|
import javafx.scene.control.TabPane;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Priority;
|
import javafx.scene.layout.Priority;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
@@ -77,7 +78,15 @@ public class ChatBoxController {
|
|||||||
() -> {
|
() -> {
|
||||||
MenuItem menuItem = new MenuItem(targetUserName);
|
MenuItem menuItem = new MenuItem(targetUserName);
|
||||||
addWhisperChatButton.getItems().add(menuItem);
|
addWhisperChatButton.getItems().add(menuItem);
|
||||||
menuItem.setOnAction(event -> addWhisperChat(targetUserName, new ChatModel(ChatType.WHISPER, username, -1, targetUserName)));
|
menuItem.setOnAction(
|
||||||
|
event ->
|
||||||
|
addWhisperChat(
|
||||||
|
targetUserName,
|
||||||
|
new ChatModel(
|
||||||
|
ChatType.WHISPER,
|
||||||
|
username,
|
||||||
|
-1,
|
||||||
|
targetUserName)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,10 +120,12 @@ public class ChatBoxController {
|
|||||||
public void addChatTab(String title, ChatModel chatModel) {
|
public void addChatTab(String title, ChatModel chatModel) {
|
||||||
URL resource = getClass().getResource(ressource);
|
URL resource = getClass().getResource(ressource);
|
||||||
FXMLLoader fxmlLoader = new FXMLLoader(resource);
|
FXMLLoader fxmlLoader = new FXMLLoader(resource);
|
||||||
runOnPlatformSynchronized(()-> {
|
runOnPlatformSynchronized(
|
||||||
|
() -> {
|
||||||
try {
|
try {
|
||||||
ChatViewController chatViewController =
|
ChatViewController chatViewController =
|
||||||
new ChatViewController(this.chatController, chatModel, this.username);
|
new ChatViewController(
|
||||||
|
this.chatController, chatModel, this.username);
|
||||||
fxmlLoader.setController(chatViewController);
|
fxmlLoader.setController(chatViewController);
|
||||||
Node load = fxmlLoader.load();
|
Node load = fxmlLoader.load();
|
||||||
VBox.setVgrow(load, Priority.ALWAYS);
|
VBox.setVgrow(load, Priority.ALWAYS);
|
||||||
@@ -133,6 +144,10 @@ public class ChatBoxController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper Function to cope with a Threads problem occurring when the main JavaFX Thread performs
|
||||||
|
* the task to add a new whisper Chat tab, and the task is specified to runLater.
|
||||||
|
*/
|
||||||
public static <T> T runOnPlatformSynchronized(Callable<T> code) {
|
public static <T> T runOnPlatformSynchronized(Callable<T> code) {
|
||||||
if (Platform.isFxApplicationThread()) {
|
if (Platform.isFxApplicationThread()) {
|
||||||
try {
|
try {
|
||||||
@@ -142,7 +157,8 @@ public class ChatBoxController {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CompletableFuture<T> futureLock = new CompletableFuture<>();
|
CompletableFuture<T> futureLock = new CompletableFuture<>();
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(
|
||||||
|
() -> {
|
||||||
try {
|
try {
|
||||||
futureLock.complete(code.call());
|
futureLock.complete(code.call());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -156,5 +172,4 @@ public class ChatBoxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,9 @@ import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
|
|||||||
import ch.unibas.dmi.dbis.cs108.casono.client.network.CoreClient;
|
import ch.unibas.dmi.dbis.cs108.casono.client.network.CoreClient;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui.ChatBoxController;
|
import ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui.ChatBoxController;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Node;
|
|
||||||
import javafx.scene.Parent;
|
import javafx.scene.Parent;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|||||||
Reference in New Issue
Block a user