Allow sending username updates

This commit is contained in:
Arnaud Vergnet 2021-01-27 10:13:13 +01:00
parent d51cbc6d75
commit 60fa5adfe4
6 changed files with 76 additions and 30 deletions

View file

@ -44,11 +44,11 @@ public class InsaPresence implements Presence {
}
@Override
public void subscribe(ParametrizedCallback<ArrayList<UserInformation>> callback, ErrorCallback errorCallback) {
public void subscribe(UserInformation userInformation, ParametrizedCallback<ArrayList<UserInformation>> callback, ErrorCallback errorCallback) {
if (!isConnected()) {
connectToPresence(
() -> proxy.connect(() -> {
sendSubscribeMessage(errorCallback);
notify(userInformation, null, errorCallback);
receiveSubscribeNotifications(callback, errorCallback);
}, errorCallback),
errorCallback);
@ -57,15 +57,6 @@ public class InsaPresence implements Presence {
}
}
/**
* Send current user information to tell the server who is subscribing
*
* @param errorCallback Called on connection error
*/
private void sendSubscribeMessage(ErrorCallback errorCallback) {
presenceConnection.send(new UserInformation(CurrentUser.getInstance()), null, errorCallback);
}
/**
* Waits for presence server response to the subscribe request
*
@ -106,6 +97,11 @@ public class InsaPresence implements Presence {
}
}
@Override
public void notify(UserInformation newInformation, @Nullable SimpleCallback callback, @Nullable ErrorCallback errorCallback) {
presenceConnection.send(newInformation, callback, errorCallback);
}
/**
* Connects to the presence server by TCP
*

View file

@ -18,12 +18,12 @@ import java.util.ArrayList;
public interface Presence {
/**
* Subscribes to this presence server notifications.
* Subscribes to this presence server notifications and publish current status.
* A list of Ids representing the current active users is returned.
*
* @param callback Called when subscription completes
*/
void subscribe(ParametrizedCallback<ArrayList<UserInformation>> callback, @Nullable ErrorCallback errorCallback);
void subscribe(UserInformation userInformation, ParametrizedCallback<ArrayList<UserInformation>> callback, @Nullable ErrorCallback errorCallback);
/**
* Stops subscription to the presence server by closing TCP connections.
@ -34,6 +34,14 @@ public interface Presence {
*/
void unsubscribe(SimpleCallback callback, @Nullable ErrorCallback errorCallback);
/**
* Notifies the presence server of any changes to the current user
*
* @param newInformation The new information to send
* @param callback Called when notify completes
*/
void notify(UserInformation newInformation, @Nullable SimpleCallback callback, @Nullable ErrorCallback errorCallback);
/**
* Gets the proxy.
* This can be used to initialize a

View file

@ -15,6 +15,7 @@ import fr.insa.clavardator.client.ui.dialogs.SnackbarController;
import fr.insa.clavardator.client.ui.users.UserListController;
import fr.insa.clavardator.client.users.CurrentUser;
import fr.insa.clavardator.client.users.UserList;
import fr.insa.clavardator.lib.users.UserInformation;
import fr.insa.clavardator.lib.util.Log;
import javafx.application.Platform;
import javafx.fxml.FXML;
@ -59,13 +60,31 @@ public class MainController implements Initializable {
online = false;
currentUser = CurrentUser.getInstance();
currentUser.addObserver(propertyChangeEvent -> {
if (propertyChangeEvent.getPropertyName().equals("state")) {
final String propertyName = propertyChangeEvent.getPropertyName();
if (propertyName.equals("state")) {
final CurrentUser.State newState = (CurrentUser.State) propertyChangeEvent.getNewValue();
onCurrentUserStateChange(newState);
} else if (propertyName.equals("username")) {
final String newUsername = (String) propertyChangeEvent.getNewValue();
onCurrentUserNameChange(newUsername);
}
});
}
private void onCurrentUserNameChange(String newUsername) {
if (online) {
if (userList != null) {
userList.propagateUsernameChange();
}
if (presenceServer != null) {
presenceServer.notify(
new UserInformation(CurrentUser.getInstance().getId(), newUsername),
null,
null);
}
}
}
/**
* If the current user becomes valid, start the chat.
* If it is invalid or not set, show the login screen.
@ -286,6 +305,7 @@ public class MainController implements Initializable {
private void subscribeToPresenceServer() {
if (presenceServer != null && online) {
presenceServer.subscribe(
new UserInformation(CurrentUser.getInstance()),
param -> userList.onReceivePresenceNotification(
param,
presenceServer.getProxy()),

View file

@ -7,6 +7,8 @@ import com.jfoenix.validation.base.ValidatorBase;
import fr.insa.clavardator.client.ui.ButtonPressEvent;
import fr.insa.clavardator.client.users.CurrentUser;
import fr.insa.clavardator.client.users.UserList;
import fr.insa.clavardator.lib.util.ParametrizedCallback;
import fr.insa.clavardator.lib.util.SimpleCallback;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
@ -179,9 +181,6 @@ public class EditUsernameDialogController implements Initializable {
if (successListener != null) {
successListener.onPress();
}
if (userList != null) {
userList.propagateUsernameChange();
}
}
/**

View file

@ -54,18 +54,20 @@ public class UserList {
if (savedUser != null) {
if (savedUser.isActive()) {
if (userInfo.getState() == UserState.DISCONNECTED) {
Log.v(getClass().getSimpleName(), "Received disconnected user from presence server already known and connected, disconnecting...");
Log.v(getClass().getSimpleName(), "Received disconnected user from presence server was already known and connected, disconnecting...");
savedUser.disconnect();
} else {
Log.v(getClass().getSimpleName(), "Received user from presence server already known and connected");
Log.v(getClass().getSimpleName(), "Received user from presence server was already known and connected, updating info...");
savedUser.setState(userInfo.getState());
savedUser.setUsername(userInfo.getUsername());
}
} else {
if (userInfo.getState() == UserState.CONNECTED) {
Log.v(getClass().getSimpleName(), "Received user from presence server already known but not connected, connecting...");
Log.v(getClass().getSimpleName(), "Received user from presence server was already known but not connected, connecting...");
savedUser.init(proxy, userInfo.id, userInfo.getUsername(),
e -> Log.e(getClass().getSimpleName(), "Error with user " + userInfo.getUsername(), e));
} else {
Log.v(getClass().getSimpleName(), "Received disconnected user from presence server already known and not connected.");
Log.v(getClass().getSimpleName(), "Received disconnected user from presence server was already known and disconnected.");
}
}
} else {

View file

@ -12,6 +12,7 @@ import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class Presence {
private static final int PRESENCE_PORT = 35650;
@ -29,17 +30,30 @@ public class Presence {
public void publish(UserInformation info) {
ArrayList<UserInformation> msg = new ArrayList<>(1);
msg.add(info);
for (TcpConnection subscriber : subscribers.values()) {
subscriber.send(msg, null,
e -> Log.e(getClass().getSimpleName(), "Error while publishing user information", e));
for (Map.Entry<String,TcpConnection> entry : subscribers.entrySet()) {
// Do not send update to self
if (!entry.getKey().equals(info.id)) {
entry.getValue().send(msg, null,
e -> Log.e(getClass().getSimpleName(), "Error while publishing user information", e));
}
}
}
private void updateUser(UserInformation userInformation) {
connectedUsers.removeIf(ui -> userInformation.id.equals(ui.id));
connectedUsers.add(userInformation);
}
private void adduser(UserInformation userInformation, TcpConnection userConnection) {
subscribers.put(userInformation.id, userConnection);
connectedUsers.add(userInformation);
}
public void subscribe(Socket socket) {
TcpConnection user = new TcpConnection(socket);
TcpConnection userConnection = new TcpConnection(socket);
// Receive user information
user.receiveOne(o -> {
userConnection.receiveOne(o -> {
if (o instanceof UserInformation) {
UserInformation userInformation = ((UserInformation) o);
Log.v(getClass().getSimpleName(), "Registering user " + userInformation.id +
@ -50,13 +64,20 @@ public class Presence {
// Send the list of connected users to the new subscriber. We're cloning it because we're modifying it
// just after this call, while the sender thread might not have send it yet
user.send((Serializable) connectedUsers.clone(), null,
userConnection.send((Serializable) connectedUsers.clone(), null,
e -> Log.e(getClass().getSimpleName(), "Error while receiving user information", e));
subscribers.put(userInformation.id, user);
connectedUsers.add(userInformation);
adduser(userInformation, userConnection);
user.receive(msg -> Log.w(getClass().getSimpleName(), "Received an unexpected message " + msg),
userConnection.receive(msg -> {
if (msg instanceof UserInformation) {
UserInformation newUserInformation = ((UserInformation) msg);
Log.v(getClass().getSimpleName(), "Receiving user status update " + newUserInformation.id +
" (" + newUserInformation.getUsername() + ")");
updateUser(newUserInformation);
publish(newUserInformation);
}
},
e -> {
if (e instanceof EOFException) {
unsubscribe(userInformation);