add username change and check for duplicates
This commit is contained in:
parent
060137115f
commit
030e9b3b0a
8 changed files with 194 additions and 77 deletions
|
@ -0,0 +1,9 @@
|
||||||
|
package fr.insa.clavardator.errors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class UsernameTakenException extends Exception implements Serializable {
|
||||||
|
public UsernameTakenException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,8 @@ import java.io.IOException;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
public class MainController implements Initializable {
|
public class MainController implements Initializable {
|
||||||
|
|
||||||
|
@ -58,8 +60,13 @@ public class MainController implements Initializable {
|
||||||
private void onCurrentUserStateChange(CurrentUser.State newState) {
|
private void onCurrentUserStateChange(CurrentUser.State newState) {
|
||||||
if (newState == CurrentUser.State.VALID)
|
if (newState == CurrentUser.State.VALID)
|
||||||
startChat();
|
startChat();
|
||||||
else
|
else {
|
||||||
Platform.runLater(() -> showLogin(newState == CurrentUser.State.INVALID));
|
final boolean isError = newState == CurrentUser.State.INVALID;
|
||||||
|
if (isError) {
|
||||||
|
endChat();
|
||||||
|
}
|
||||||
|
Platform.runLater(() -> showLogin(isError));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openEditUsernameDialog(EditUsernameDialogController.Mode mode) {
|
private void openEditUsernameDialog(EditUsernameDialogController.Mode mode) {
|
||||||
|
@ -72,11 +79,11 @@ public class MainController implements Initializable {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
editUserDialogController.setOnSuccessListener(() -> {
|
editUserDialogController.setOnSuccessListener(() -> {
|
||||||
if (!initialMode) {
|
if (mode == EditUsernameDialogController.Mode.EDIT) {
|
||||||
showSnackbarEvent("Nom d'utilisateur changé !", SnackbarController.Mode.SUCCESS);
|
showSnackbarEvent("Nom d'utilisateur changé !", SnackbarController.Mode.SUCCESS);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
editUserDialogController.show(root, mode);
|
Platform.runLater(() -> editUserDialogController.show(root, mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showSnackbarEvent(String text, SnackbarController.Mode mode) {
|
private void showSnackbarEvent(String text, SnackbarController.Mode mode) {
|
||||||
|
@ -99,15 +106,26 @@ public class MainController implements Initializable {
|
||||||
|
|
||||||
private void discoverActiveUsers() {
|
private void discoverActiveUsers() {
|
||||||
if (userList != null) {
|
if (userList != null) {
|
||||||
userList.discoverActiveUsers((e) -> CurrentUser.getInstance().setState(CurrentUser.State.INVALID));
|
userList.discoverActiveUsers((e) -> {
|
||||||
|
Log.e(this.getClass().getSimpleName(), "Error discovering users", e);
|
||||||
|
CurrentUser.getInstance().setState(CurrentUser.State.INVALID);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startListening() {
|
private void startListening() {
|
||||||
if (userList != null) {
|
if (userList != null) {
|
||||||
userList.startDiscoveryListening();
|
userList.startDiscoveryListening();
|
||||||
userList.startUserListening((e) ->
|
userList.startUserListening((e) -> {
|
||||||
Log.e(this.getClass().getSimpleName(), "Error listening to users", e));
|
Log.e(this.getClass().getSimpleName(), "Error listening to users", e);
|
||||||
|
CurrentUser.getInstance().setState(CurrentUser.State.INVALID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopListening() {
|
||||||
|
if (userList != null) {
|
||||||
|
userList.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,6 +136,11 @@ public class MainController implements Initializable {
|
||||||
Platform.runLater(this::showChat);
|
Platform.runLater(this::showChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void endChat() {
|
||||||
|
Log.v(this.getClass().getSimpleName(), "Chat ended");
|
||||||
|
stopListening();
|
||||||
|
}
|
||||||
|
|
||||||
private void showChat() {
|
private void showChat() {
|
||||||
Log.v(this.getClass().getSimpleName(), "Chat shown");
|
Log.v(this.getClass().getSimpleName(), "Chat shown");
|
||||||
loadingController.hide();
|
loadingController.hide();
|
||||||
|
@ -128,7 +151,14 @@ public class MainController implements Initializable {
|
||||||
Log.v(this.getClass().getSimpleName(), "Login shown");
|
Log.v(this.getClass().getSimpleName(), "Login shown");
|
||||||
mainContainer.setVisible(false);
|
mainContainer.setVisible(false);
|
||||||
loadingController.hide();
|
loadingController.hide();
|
||||||
openEditUsernameDialog(isError ? EditUsernameDialogController.Mode.ERROR : EditUsernameDialogController.Mode.INITIAL);
|
Timer t = new Timer();
|
||||||
|
t.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
openEditUsernameDialog(isError ? EditUsernameDialogController.Mode.ERROR : EditUsernameDialogController.Mode.INITIAL);
|
||||||
|
t.cancel();
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showError() {
|
private void showError() {
|
||||||
|
@ -162,5 +192,6 @@ public class MainController implements Initializable {
|
||||||
this.userList = userList;
|
this.userList = userList;
|
||||||
listController.setUserList(userList);
|
listController.setUserList(userList);
|
||||||
listController.setRefreshUserListener(this::discoverActiveUsers);
|
listController.setRefreshUserListener(this::discoverActiveUsers);
|
||||||
|
editUserDialogController.setUserList(userList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import com.jfoenix.controls.JFXTextField;
|
||||||
import com.jfoenix.validation.base.ValidatorBase;
|
import com.jfoenix.validation.base.ValidatorBase;
|
||||||
import fr.insa.clavardator.ui.ButtonPressEvent;
|
import fr.insa.clavardator.ui.ButtonPressEvent;
|
||||||
import fr.insa.clavardator.users.CurrentUser;
|
import fr.insa.clavardator.users.CurrentUser;
|
||||||
|
import fr.insa.clavardator.users.UserList;
|
||||||
import javafx.beans.property.ReadOnlyBooleanWrapper;
|
import javafx.beans.property.ReadOnlyBooleanWrapper;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
@ -16,8 +17,6 @@ import javafx.scene.layout.StackPane;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
public class EditUsernameDialogController implements Initializable {
|
public class EditUsernameDialogController implements Initializable {
|
||||||
|
|
||||||
|
@ -44,21 +43,16 @@ public class EditUsernameDialogController implements Initializable {
|
||||||
private Validator validator;
|
private Validator validator;
|
||||||
private ButtonPressEvent successListener;
|
private ButtonPressEvent successListener;
|
||||||
private ButtonPressEvent cancelListener;
|
private ButtonPressEvent cancelListener;
|
||||||
|
private UserList userList;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void onConfirm() {
|
private void onConfirm() {
|
||||||
setLocked(true);
|
setLocked(true);
|
||||||
CurrentUser.getInstance().setUsername(textField.getText());
|
if (userList != null && userList.isUsernameAvailable(textField.getText())) {
|
||||||
// TODO replace by network call
|
onSuccess();
|
||||||
Timer t = new Timer();
|
} else {
|
||||||
t.schedule(new TimerTask() {
|
onError();
|
||||||
@Override
|
}
|
||||||
public void run() {
|
|
||||||
// onError();
|
|
||||||
onSuccess();
|
|
||||||
t.cancel();
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
|
@ -69,6 +63,10 @@ public class EditUsernameDialogController implements Initializable {
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setUserList(UserList userList) {
|
||||||
|
this.userList = userList;
|
||||||
|
}
|
||||||
|
|
||||||
public void setOnSuccessListener(ButtonPressEvent listener) {
|
public void setOnSuccessListener(ButtonPressEvent listener) {
|
||||||
this.successListener = listener;
|
this.successListener = listener;
|
||||||
}
|
}
|
||||||
|
@ -149,9 +147,14 @@ public class EditUsernameDialogController implements Initializable {
|
||||||
setFieldError(State.VALID);
|
setFieldError(State.VALID);
|
||||||
setLocked(false);
|
setLocked(false);
|
||||||
hide();
|
hide();
|
||||||
|
final String newName = textField.getText();
|
||||||
|
CurrentUser.getInstance().setUsername(newName);
|
||||||
if (successListener != null) {
|
if (successListener != null) {
|
||||||
successListener.onPress();
|
successListener.onPress();
|
||||||
}
|
}
|
||||||
|
if (userList != null) {
|
||||||
|
userList.propagateUsernameChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onError() {
|
private void onError() {
|
||||||
|
|
|
@ -55,8 +55,12 @@ public class UserListController implements Initializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onUserConnected(PeerUser user) {
|
private void onUserConnected(PeerUser user) {
|
||||||
Log.v(this.getClass().getSimpleName(), "Add user to UI");
|
if (!peerUserListView.getItems().contains(user)) {
|
||||||
Platform.runLater(() -> peerUserListView.getItems().add(user));
|
Log.v(this.getClass().getSimpleName(), "Add user to UI");
|
||||||
|
Platform.runLater(() -> peerUserListView.getItems().add(user));
|
||||||
|
} else {
|
||||||
|
Log.w(this.getClass().getSimpleName(), "User already added to ui, skipping...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUserList(UserList userList) {
|
public void setUserList(UserList userList) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package fr.insa.clavardator.users;
|
||||||
|
|
||||||
import fr.insa.clavardator.chat.ChatHistory;
|
import fr.insa.clavardator.chat.ChatHistory;
|
||||||
import fr.insa.clavardator.chat.Message;
|
import fr.insa.clavardator.chat.Message;
|
||||||
|
import fr.insa.clavardator.errors.UsernameTakenException;
|
||||||
import fr.insa.clavardator.network.PeerConnection;
|
import fr.insa.clavardator.network.PeerConnection;
|
||||||
import fr.insa.clavardator.util.ErrorCallback;
|
import fr.insa.clavardator.util.ErrorCallback;
|
||||||
import fr.insa.clavardator.util.Log;
|
import fr.insa.clavardator.util.Log;
|
||||||
|
@ -35,16 +36,14 @@ public class PeerUser extends User implements Comparable<PeerUser> {
|
||||||
* @param callback The function to call on success
|
* @param callback The function to call on success
|
||||||
* @param errorCallback The function to call on socket error
|
* @param errorCallback The function to call on socket error
|
||||||
*/
|
*/
|
||||||
public void connect(InetAddress ipAddr, UserConnectedCallback callback, ErrorCallback errorCallback) {
|
public void createConnection(InetAddress ipAddr, UserConnectedCallback callback, ErrorCallback errorCallback) {
|
||||||
if (connection != null && connection.isOpen()) {
|
closeConnection();
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
Log.v(this.getClass().getSimpleName(), "Creating new TCP connection with " + id);
|
Log.v(this.getClass().getSimpleName(), "Creating new TCP connection with " + id);
|
||||||
// Connect to the peer
|
// Connect to the peer
|
||||||
setState(State.CONNECTING);
|
setState(State.CONNECTING);
|
||||||
connection = new PeerConnection(
|
connection = new PeerConnection(
|
||||||
ipAddr,
|
ipAddr,
|
||||||
(thisConnection) -> init(thisConnection, callback, errorCallback),
|
(thisConnection) -> init(thisConnection, false, callback, errorCallback),
|
||||||
e -> {
|
e -> {
|
||||||
Log.e(this.getClass().getSimpleName(), "Could not create TCP connection with " + id, e);
|
Log.e(this.getClass().getSimpleName(), "Could not create TCP connection with " + id, e);
|
||||||
disconnect();
|
disconnect();
|
||||||
|
@ -59,17 +58,20 @@ public class PeerUser extends User implements Comparable<PeerUser> {
|
||||||
* @param callback The function to call on success, with the new ActiveUser as parameter
|
* @param callback The function to call on success, with the new ActiveUser as parameter
|
||||||
* @param errorCallback The function to call on socket error
|
* @param errorCallback The function to call on socket error
|
||||||
*/
|
*/
|
||||||
public void connect(Socket socket, UserConnectedCallback callback, ErrorCallback errorCallback) {
|
public void acceptConnection(Socket socket, UserConnectedCallback callback, ErrorCallback errorCallback) {
|
||||||
if (connection != null && connection.isOpen()) {
|
closeConnection();
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
setState(State.CONNECTING);
|
setState(State.CONNECTING);
|
||||||
connection = new PeerConnection(socket);
|
connection = new PeerConnection(socket);
|
||||||
|
init(connection, true, callback, errorCallback);
|
||||||
init(connection, callback, errorCallback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendTextMessage(String msg, @Nullable ErrorCallback errorCallback) {
|
/**
|
||||||
|
* Sends a basic text message to this user
|
||||||
|
*
|
||||||
|
* @param msg The text message to send
|
||||||
|
* @param errorCallback Callback on error
|
||||||
|
*/
|
||||||
|
public void sendTextMessage(String msg, @Nullable ErrorCallback errorCallback) {
|
||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
Log.v(this.getClass().getSimpleName(),
|
Log.v(this.getClass().getSimpleName(),
|
||||||
"Sending message to " + this.getUsername() + " / " + this.getId() + ": " + msg);
|
"Sending message to " + this.getUsername() + " / " + this.getId() + ": " + msg);
|
||||||
|
@ -83,38 +85,81 @@ public class PeerUser extends User implements Comparable<PeerUser> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init(PeerConnection thisConnection, UserConnectedCallback callback, ErrorCallback errorCallback) {
|
/**
|
||||||
|
* Sends current user information to this user
|
||||||
|
*
|
||||||
|
* @param errorCallback Callback on error
|
||||||
|
*/
|
||||||
|
public void sendCurrentUser(@Nullable ErrorCallback errorCallback) {
|
||||||
|
if (connection != null) {
|
||||||
|
final String username = CurrentUser.getInstance().getUsername();
|
||||||
|
Log.v(this.getClass().getSimpleName(),
|
||||||
|
"Sending current user information to " + this.getUsername() + " / " + this.getId() + ": " + username);
|
||||||
|
connection.send(
|
||||||
|
new UserInformation(CurrentUser.getInstance()),
|
||||||
|
null,
|
||||||
|
errorCallback);
|
||||||
|
} else {
|
||||||
|
Log.e(this.getClass().getSimpleName(), "Could not send new username: connection is not initialized");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendUsernameTaken(PeerConnection thisConnection) {
|
||||||
|
Log.v(this.getClass().getSimpleName(), "Received username request using current username");
|
||||||
|
thisConnection.send(new UsernameTakenException("Username taken"), this::disconnect, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the connection with this user.
|
||||||
|
* Both user exchange their information
|
||||||
|
*
|
||||||
|
* @param thisConnection The peer connection to use
|
||||||
|
* @param callback Callback on success
|
||||||
|
* @param errorCallback Callback on error
|
||||||
|
*/
|
||||||
|
private void init(PeerConnection thisConnection, boolean isReceiving, UserConnectedCallback callback, ErrorCallback errorCallback) {
|
||||||
// Send our username
|
// Send our username
|
||||||
String currentUserUsername = CurrentUser.getInstance().getUsername();
|
thisConnection.send(new UserInformation(CurrentUser.getInstance()), null, e -> {
|
||||||
int currentUserId = CurrentUser.getInstance().getId();
|
|
||||||
thisConnection.send(new UserInformation(currentUserId, currentUserUsername), null, e -> {
|
|
||||||
disconnect();
|
disconnect();
|
||||||
errorCallback.onError(e);
|
errorCallback.onError(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Receive peer's username
|
// Receive peer's username
|
||||||
thisConnection.receiveOne(msg -> {
|
thisConnection.receiveOne(msg -> {
|
||||||
assert msg instanceof UserInformation;
|
if (msg instanceof UserInformation) {
|
||||||
UserInformation userInfo = (UserInformation) msg;
|
UserInformation userInfo = (UserInformation) msg;
|
||||||
// TODO : Check username unique
|
final String receivedUsername = userInfo.getUsername();
|
||||||
assert id == userInfo.id;
|
if (!receivedUsername.equals(CurrentUser.getInstance().getUsername())) {
|
||||||
setUsername(userInfo.getUsername());
|
setUsername(receivedUsername);
|
||||||
callback.onUserConnected();
|
callback.onUserConnected();
|
||||||
|
subscribeToMessages(e -> {
|
||||||
// Subscribe to incoming messages
|
disconnect();
|
||||||
subscribeToMessages(e -> {
|
errorCallback.onError(e);
|
||||||
|
});
|
||||||
|
setState(State.CONNECTED);
|
||||||
|
} else if (isReceiving) {
|
||||||
|
sendUsernameTaken(thisConnection);
|
||||||
|
} else {
|
||||||
|
disconnect();
|
||||||
|
errorCallback.onError(new Exception("Tried to use same username as remote"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
disconnect();
|
disconnect();
|
||||||
errorCallback.onError(e);
|
errorCallback.onError(new Exception("Did not receive remote username"));
|
||||||
});
|
}
|
||||||
setState(State.CONNECTED);
|
|
||||||
|
|
||||||
}, e -> {
|
}, e -> {
|
||||||
disconnect();
|
disconnect();
|
||||||
errorCallback.onError(e);
|
errorCallback.onError(e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to this user messages.
|
||||||
|
* If receiving new user info, update this user.
|
||||||
|
* If receiving text message, store it in the history.
|
||||||
|
*
|
||||||
|
* @param errorCallback Callback on error
|
||||||
|
*/
|
||||||
private void subscribeToMessages(ErrorCallback errorCallback) {
|
private void subscribeToMessages(ErrorCallback errorCallback) {
|
||||||
connection.receive(
|
connection.receive(
|
||||||
msg -> {
|
msg -> {
|
||||||
|
@ -139,19 +184,28 @@ public class PeerUser extends User implements Comparable<PeerUser> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the connection and set state to disconnected
|
||||||
|
*/
|
||||||
public void disconnect() {
|
public void disconnect() {
|
||||||
Log.v(this.getClass().getSimpleName(), "Disconnecting from user: " + id);
|
Log.v(this.getClass().getSimpleName(), "Disconnecting from user: " + id);
|
||||||
|
closeConnection();
|
||||||
|
setState(State.DISCONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the connection to this user
|
||||||
|
*/
|
||||||
|
private void closeConnection() {
|
||||||
if (connection != null && connection.isOpen()) {
|
if (connection != null && connection.isOpen()) {
|
||||||
connection.close();
|
connection.close();
|
||||||
connection = null;
|
connection = null;
|
||||||
}
|
}
|
||||||
setState(State.DISCONNECTED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value of history
|
* Gets the value of history
|
||||||
*
|
*
|
||||||
* @return the value of history
|
* @return the value of history
|
||||||
*/
|
*/
|
||||||
|
@ -159,11 +213,21 @@ public class PeerUser extends User implements Comparable<PeerUser> {
|
||||||
return history;
|
return history;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this user state
|
||||||
|
*
|
||||||
|
* @param state The new state
|
||||||
|
*/
|
||||||
private void setState(State state) {
|
private void setState(State state) {
|
||||||
pcs.firePropertyChange("state", this.state, state);
|
pcs.firePropertyChange("state", this.state, state);
|
||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this user is active.
|
||||||
|
*
|
||||||
|
* @return True id active, false otherwise
|
||||||
|
*/
|
||||||
public boolean isActive() {
|
public boolean isActive() {
|
||||||
return state == State.CONNECTED;
|
return state == State.CONNECTED;
|
||||||
}
|
}
|
||||||
|
@ -178,12 +242,18 @@ public class PeerUser extends User implements Comparable<PeerUser> {
|
||||||
return getUsername().compareTo(peerUser.getUsername());
|
return getUsername().compareTo(peerUser.getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user connection state
|
||||||
|
*/
|
||||||
public enum State {
|
public enum State {
|
||||||
CONNECTING,
|
CONNECTING,
|
||||||
CONNECTED,
|
CONNECTED,
|
||||||
DISCONNECTED,
|
DISCONNECTED,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback when this user successfully connects
|
||||||
|
*/
|
||||||
public interface UserConnectedCallback {
|
public interface UserConnectedCallback {
|
||||||
void onUserConnected();
|
void onUserConnected();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package fr.insa.clavardator.users;
|
package fr.insa.clavardator.users;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.beans.PropertyChangeSupport;
|
import java.beans.PropertyChangeSupport;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
|
@ -2,6 +2,9 @@ package fr.insa.clavardator.users;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used to serialize useful user information
|
||||||
|
*/
|
||||||
public class UserInformation implements Serializable {
|
public class UserInformation implements Serializable {
|
||||||
public final int id;
|
public final int id;
|
||||||
private final String username;
|
private final String username;
|
||||||
|
|
|
@ -38,10 +38,9 @@ public class UserList {
|
||||||
netDiscoverer.discoverActiveUsers("CLAVARDATOR_BROADCAST", (ipAddr, data) -> {
|
netDiscoverer.discoverActiveUsers("CLAVARDATOR_BROADCAST", (ipAddr, data) -> {
|
||||||
int id = getIdFromIp(ipAddr);
|
int id = getIdFromIp(ipAddr);
|
||||||
Log.v(this.getClass().getSimpleName(), "Discovered new user: " + id);
|
Log.v(this.getClass().getSimpleName(), "Discovered new user: " + id);
|
||||||
final PeerUser finalUser = createNewUser(id);
|
final PeerUser user = createNewUser(id);
|
||||||
if (finalUser != null) {
|
if (user != null) {
|
||||||
finalUser.connect(ipAddr, () ->
|
user.createConnection(ipAddr, () -> onUserConnectionSuccess(user), errorCallback);
|
||||||
finalUser.addObserver(evt -> userChangeObserver(finalUser, evt)), errorCallback);
|
|
||||||
}
|
}
|
||||||
}, errorCallback);
|
}, errorCallback);
|
||||||
}
|
}
|
||||||
|
@ -56,17 +55,22 @@ public class UserList {
|
||||||
public void startUserListening(ErrorCallback errorCallback) {
|
public void startUserListening(ErrorCallback errorCallback) {
|
||||||
connectionListener.acceptConnection(
|
connectionListener.acceptConnection(
|
||||||
(clientSocket) -> {
|
(clientSocket) -> {
|
||||||
int id = getIdFromIp(clientSocket.getInetAddress());
|
final int id = getIdFromIp(clientSocket.getInetAddress());
|
||||||
Log.v(this.getClass().getSimpleName(), "new connection from user: " + id);
|
Log.v(this.getClass().getSimpleName(), "new connection from user: " + id);
|
||||||
final PeerUser finalUser = createNewUser(id);
|
final PeerUser user = createNewUser(id);
|
||||||
if (finalUser != null) {
|
if (user != null) {
|
||||||
finalUser.connect(clientSocket, () ->
|
user.acceptConnection(clientSocket, () ->
|
||||||
finalUser.addObserver(evt -> userChangeObserver(finalUser, evt)), errorCallback);
|
onUserConnectionSuccess(user), errorCallback);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
errorCallback);
|
errorCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onUserConnectionSuccess(PeerUser user) {
|
||||||
|
notifyNewUserObservers(user);
|
||||||
|
user.addObserver(evt -> userChangeObserver(user, evt));
|
||||||
|
}
|
||||||
|
|
||||||
private PeerUser createNewUser(int id) {
|
private PeerUser createNewUser(int id) {
|
||||||
// If already connected, warn and return
|
// If already connected, warn and return
|
||||||
if (activeUsers.containsKey(id)) {
|
if (activeUsers.containsKey(id)) {
|
||||||
|
@ -82,7 +86,6 @@ public class UserList {
|
||||||
// Username is set on TCP connection start
|
// Username is set on TCP connection start
|
||||||
user = new PeerUser(id);
|
user = new PeerUser(id);
|
||||||
inactiveUsers.put(id, user);
|
inactiveUsers.put(id, user);
|
||||||
notifyNewUserObservers(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
|
@ -146,18 +149,18 @@ public class UserList {
|
||||||
* @return True if the username is available
|
* @return True if the username is available
|
||||||
*/
|
*/
|
||||||
public boolean isUsernameAvailable(String username) {
|
public boolean isUsernameAvailable(String username) {
|
||||||
Predicate<User> usernameEqual = user -> user.getUsername().equals(username);
|
Predicate<User> usernameEqual = user -> user.getUsername() != null && user.getUsername().equals(username);
|
||||||
return activeUsers.values().stream().noneMatch(usernameEqual) &&
|
return activeUsers.values().stream().noneMatch(usernameEqual) &&
|
||||||
inactiveUsers.values().stream().noneMatch(usernameEqual);
|
inactiveUsers.values().stream().noneMatch(usernameEqual);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell all active users that our username changed
|
* Tell all active users that our username changed
|
||||||
*
|
|
||||||
* @param username The new username
|
|
||||||
*/
|
*/
|
||||||
public void propagateUsernameChange(String username) {
|
public void propagateUsernameChange() {
|
||||||
// TODO
|
activeUsers.forEach((id, user) -> {
|
||||||
|
user.sendCurrentUser(Throwable::printStackTrace);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,8 +180,4 @@ public class UserList {
|
||||||
void onUserConnected(PeerUser user);
|
void onUserConnected(PeerUser user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface UserDisconnectionCallback {
|
|
||||||
void onUserDisconnected(PeerUser user);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue