Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 5 additions & 13 deletions NetworkChatClient/NetworkChatClient.iml
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_11">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.openjfx:javafx-controls:14.0.1" level="project" />
<orderEntry type="library" name="Maven: org.openjfx:javafx-controls:win:14.0.1" level="project" />
<orderEntry type="library" name="Maven: org.openjfx:javafx-graphics:14.0.1" level="project" />
<orderEntry type="library" name="Maven: org.openjfx:javafx-graphics:win:14.0.1" level="project" />
<orderEntry type="library" name="Maven: org.openjfx:javafx-base:14.0.1" level="project" />
<orderEntry type="library" name="Maven: org.openjfx:javafx-base:win:14.0.1" level="project" />
<orderEntry type="library" name="Maven: org.openjfx:javafx-fxml:14.0.1" level="project" />
<orderEntry type="library" name="Maven: org.openjfx:javafx-fxml:win:14.0.1" level="project" />
<orderEntry type="library" name="JavaFX" level="project" />
<orderEntry type="module" module-name="NetworkChatClientServer" />
</component>
</module>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Parent;
Expand Down Expand Up @@ -30,6 +31,10 @@ public class ClientChat extends Application {
private Network network;
private ViewController viewController;

public void updateUsers(List<String> users) {
viewController.usersList.setItems(FXCollections.observableList(users));
}

@Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
Expand Down Expand Up @@ -120,10 +125,6 @@ public ClientChatState getState() {
return state;
}

public void setState(ClientChatState state) {
this.state = state;
}

public void activeChatDialog(String nickname) {
primaryStage.setTitle(nickname);
state = ClientChatState.CHAT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ public void executeAuth(ActionEvent actionEvent) {
return;
}

String authCommandMessage = String.format("%s %s %s", AUTH_CMD, login, password);
try {
network.sendMessage(authCommandMessage);
network.sendAuthMessage(login, password);
} catch (IOException e) {
ClientChat.showNetworkError(e.getMessage(), "Auth error!", null);
e.printStackTrace();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.*;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
import ru.geekbrains.java2.chat.client.ClientChat;
import ru.geekbrains.java2.chat.client.models.Network;
Expand All @@ -26,10 +24,33 @@ public class ViewController {
private Network network;
private Stage primaryStage;

private String selectedRecipient;

@FXML
public void initialize() {

usersList.setItems(FXCollections.observableArrayList(ClientChat.USERS_TEST_DATA));
textField.requestFocus();

usersList.setCellFactory(lv -> {
MultipleSelectionModel<String> selectionModel = usersList.getSelectionModel();
ListCell<String> cell = new ListCell<>();
cell.textProperty().bind(cell.itemProperty());
cell.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
usersList.requestFocus();
if (! cell.isEmpty()) {
int index = cell.getIndex();
if (selectionModel.getSelectedIndices().contains(index)) {
selectionModel.clearSelection(index);
selectedRecipient = null;
} else {
selectionModel.select(index);
selectedRecipient = cell.getItem();
}
event.consume();
}
});
return cell ;
});
}

@FXML
Expand All @@ -39,7 +60,11 @@ private void sendMessage() {
textField.clear();

try {
network.sendMessage(message);
if (selectedRecipient != null) {
network.sendPrivateMessage(selectedRecipient, message);
} else {
network.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
String errorMessage = "Failed to send message";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
import javafx.application.Platform;
import ru.geekbrains.java2.chat.client.ClientChat;
import ru.geekbrains.java2.chat.client.controllers.ViewController;
import ru.geekbrains.java2.chat.clientserver.Command;
import ru.geekbrains.java2.chat.clientserver.commands.*;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.*;
import java.net.Socket;

import static ru.geekbrains.java2.chat.clientserver.Command.*;

public class Network {

private static final String SERVER_ADDRESS = "localhost";
private static final int SERVER_PORT = 8189;

private static final String AUTH_OK_CMD = "/authok";

private String host;
private int port;
private DataInputStream inputStream;
private DataOutputStream outputStream;
private ObjectInputStream inputStream;
private ObjectOutputStream outputStream;
private Socket socket;
private ClientChat clientChat;
private String nickname;
Expand All @@ -41,8 +41,8 @@ public Network(ClientChat clientChat) {
public boolean connect() {
try {
socket = new Socket(host, port);
inputStream = new DataInputStream(socket.getInputStream());
outputStream = new DataOutputStream(socket.getOutputStream());
outputStream = new ObjectOutputStream(socket.getOutputStream());
inputStream = new ObjectInputStream(socket.getInputStream());
return true;
} catch (IOException e) {
System.err.println("Соединение не было установлено!");
Expand All @@ -51,55 +51,100 @@ public boolean connect() {
}
}

public DataInputStream getInputStream() {
return inputStream;
public void sendPrivateMessage(String receiver, String message) throws IOException {
sendCommand(privateMessageCommand(receiver, message));
}

public DataOutputStream getOutputStream() {
return outputStream;
public void sendMessage(String message) throws IOException {
sendCommand(publicMessageCommand(nickname, message));
}

public void sendMessage(String message) throws IOException {
getOutputStream().writeUTF(message);
private void sendCommand(Command command) throws IOException {
outputStream.writeObject(command);
}

public void waitMessages(ViewController viewController) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
String message = inputStream.readUTF();
if (clientChat.getState() == ClientChatState.AUTHENTICATION) {
if (message.startsWith(AUTH_OK_CMD)) {
String[] parts = message.split(" ", 2);
nickname = parts[1];
Platform.runLater(() -> {
clientChat.activeChatDialog(nickname);
});
}
else {
Platform.runLater(() -> {
ClientChat.showNetworkError(message, "Auth error", null);
});
}
}
else {
Platform.runLater(() -> {
viewController.appendMessage(message);
});
}
Thread thread = new Thread(() -> {
try {
while (true) {
Command command = readCommand();
if (command == null) {
continue;
}

if (clientChat.getState() == ClientChatState.AUTHENTICATION) {
processAuthResult(command);
} else {
processMessage(viewController, command);
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("Соединение было потеряно!");
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("Соединение было потеряно!");
}
});
thread.setDaemon(true);
thread.start();
}

private void processMessage(ViewController viewController, Command command) {
switch (command.getType()) {
case INFO_MESSAGE: {
MessageInfoCommandData data = (MessageInfoCommandData) command.getData();
Platform.runLater(() -> {
viewController.appendMessage(data.getMessage());
});
break;
}
case CLIENT_MESSAGE: {
ClientMessageCommandData data = (ClientMessageCommandData) command.getData();
String sender = data.getSender();
String message = data.getMessage();
Platform.runLater(() -> {
viewController.appendMessage(String.format("%s: %s", sender, message));
});
break;
}
case ERROR: {
ErrorCommandData data = (ErrorCommandData) command.getData();
Platform.runLater(() -> {
ClientChat.showNetworkError(data.getErrorMessage(), "Server error", null);
});
break;
}
case UPDATE_USERS_LIST: {
UpdateUsersListCommandData data = (UpdateUsersListCommandData) command.getData();
Platform.runLater(() -> {
clientChat.updateUsers(data.getUsers());
});
break;
}
default:
throw new IllegalArgumentException("Uknown command type: " + command.getType());
}
}

private void processAuthResult(Command command) {
switch (command.getType()) {
case AUTH_OK: {
AuthOkCommandData data = (AuthOkCommandData) command.getData();
nickname = data.getUsername();
Platform.runLater(() -> {
clientChat.activeChatDialog(nickname);
});
break;
}
case ERROR:
ErrorCommandData data = (ErrorCommandData) command.getData();
Platform.runLater(() -> {
ClientChat.showNetworkError(data.getErrorMessage(), "Auth error", null);
});
break;
default:
throw new IllegalArgumentException("Uknown command type: " + command.getType());
}
}

public void close() {
try {
if (socket != null && socket.isConnected()) {
Expand All @@ -109,4 +154,20 @@ public void close() {
e.printStackTrace();
}
}

private Command readCommand() throws IOException {
Command command = null;
try {
command = (Command) inputStream.readObject();
} catch (ClassNotFoundException e) {
System.err.println("Failed to read Command class");
e.printStackTrace();
}

return command;
}

public void sendAuthMessage(String login, String password) throws IOException {
sendCommand(authCommand(login, password));
}
}
11 changes: 11 additions & 0 deletions NetworkChatClientServer/NetworkChatClientServer.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
Loading