Allow sending username updates
This commit is contained in:
parent
d51cbc6d75
commit
60fa5adfe4
6 changed files with 76 additions and 30 deletions
|
@ -44,11 +44,11 @@ public class InsaPresence implements Presence {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void subscribe(ParametrizedCallback<ArrayList<UserInformation>> callback, ErrorCallback errorCallback) {
|
public void subscribe(UserInformation userInformation, ParametrizedCallback<ArrayList<UserInformation>> callback, ErrorCallback errorCallback) {
|
||||||
if (!isConnected()) {
|
if (!isConnected()) {
|
||||||
connectToPresence(
|
connectToPresence(
|
||||||
() -> proxy.connect(() -> {
|
() -> proxy.connect(() -> {
|
||||||
sendSubscribeMessage(errorCallback);
|
notify(userInformation, null, errorCallback);
|
||||||
receiveSubscribeNotifications(callback, errorCallback);
|
receiveSubscribeNotifications(callback, errorCallback);
|
||||||
}, errorCallback),
|
}, 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
|
* 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
|
* Connects to the presence server by TCP
|
||||||
*
|
*
|
||||||
|
|
|
@ -18,12 +18,12 @@ import java.util.ArrayList;
|
||||||
public interface Presence {
|
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.
|
* A list of Ids representing the current active users is returned.
|
||||||
*
|
*
|
||||||
* @param callback Called when subscription completes
|
* @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.
|
* Stops subscription to the presence server by closing TCP connections.
|
||||||
|
@ -34,6 +34,14 @@ public interface Presence {
|
||||||
*/
|
*/
|
||||||
void unsubscribe(SimpleCallback callback, @Nullable ErrorCallback errorCallback);
|
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.
|
* Gets the proxy.
|
||||||
* This can be used to initialize a
|
* This can be used to initialize a
|
||||||
|
|
|
@ -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.ui.users.UserListController;
|
||||||
import fr.insa.clavardator.client.users.CurrentUser;
|
import fr.insa.clavardator.client.users.CurrentUser;
|
||||||
import fr.insa.clavardator.client.users.UserList;
|
import fr.insa.clavardator.client.users.UserList;
|
||||||
|
import fr.insa.clavardator.lib.users.UserInformation;
|
||||||
import fr.insa.clavardator.lib.util.Log;
|
import fr.insa.clavardator.lib.util.Log;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
@ -59,13 +60,31 @@ public class MainController implements Initializable {
|
||||||
online = false;
|
online = false;
|
||||||
currentUser = CurrentUser.getInstance();
|
currentUser = CurrentUser.getInstance();
|
||||||
currentUser.addObserver(propertyChangeEvent -> {
|
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();
|
final CurrentUser.State newState = (CurrentUser.State) propertyChangeEvent.getNewValue();
|
||||||
onCurrentUserStateChange(newState);
|
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 the current user becomes valid, start the chat.
|
||||||
* If it is invalid or not set, show the login screen.
|
* If it is invalid or not set, show the login screen.
|
||||||
|
@ -286,6 +305,7 @@ public class MainController implements Initializable {
|
||||||
private void subscribeToPresenceServer() {
|
private void subscribeToPresenceServer() {
|
||||||
if (presenceServer != null && online) {
|
if (presenceServer != null && online) {
|
||||||
presenceServer.subscribe(
|
presenceServer.subscribe(
|
||||||
|
new UserInformation(CurrentUser.getInstance()),
|
||||||
param -> userList.onReceivePresenceNotification(
|
param -> userList.onReceivePresenceNotification(
|
||||||
param,
|
param,
|
||||||
presenceServer.getProxy()),
|
presenceServer.getProxy()),
|
||||||
|
|
|
@ -7,6 +7,8 @@ import com.jfoenix.validation.base.ValidatorBase;
|
||||||
import fr.insa.clavardator.client.ui.ButtonPressEvent;
|
import fr.insa.clavardator.client.ui.ButtonPressEvent;
|
||||||
import fr.insa.clavardator.client.users.CurrentUser;
|
import fr.insa.clavardator.client.users.CurrentUser;
|
||||||
import fr.insa.clavardator.client.users.UserList;
|
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.property.ReadOnlyBooleanWrapper;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
@ -179,9 +181,6 @@ public class EditUsernameDialogController implements Initializable {
|
||||||
if (successListener != null) {
|
if (successListener != null) {
|
||||||
successListener.onPress();
|
successListener.onPress();
|
||||||
}
|
}
|
||||||
if (userList != null) {
|
|
||||||
userList.propagateUsernameChange();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -54,18 +54,20 @@ public class UserList {
|
||||||
if (savedUser != null) {
|
if (savedUser != null) {
|
||||||
if (savedUser.isActive()) {
|
if (savedUser.isActive()) {
|
||||||
if (userInfo.getState() == UserState.DISCONNECTED) {
|
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();
|
savedUser.disconnect();
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
if (userInfo.getState() == UserState.CONNECTED) {
|
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(),
|
savedUser.init(proxy, userInfo.id, userInfo.getUsername(),
|
||||||
e -> Log.e(getClass().getSimpleName(), "Error with user " + userInfo.getUsername(), e));
|
e -> Log.e(getClass().getSimpleName(), "Error with user " + userInfo.getUsername(), e));
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import java.net.Socket;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class Presence {
|
public class Presence {
|
||||||
private static final int PRESENCE_PORT = 35650;
|
private static final int PRESENCE_PORT = 35650;
|
||||||
|
@ -29,17 +30,30 @@ public class Presence {
|
||||||
public void publish(UserInformation info) {
|
public void publish(UserInformation info) {
|
||||||
ArrayList<UserInformation> msg = new ArrayList<>(1);
|
ArrayList<UserInformation> msg = new ArrayList<>(1);
|
||||||
msg.add(info);
|
msg.add(info);
|
||||||
for (TcpConnection subscriber : subscribers.values()) {
|
for (Map.Entry<String,TcpConnection> entry : subscribers.entrySet()) {
|
||||||
subscriber.send(msg, null,
|
// Do not send update to self
|
||||||
e -> Log.e(getClass().getSimpleName(), "Error while publishing user information", e));
|
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) {
|
public void subscribe(Socket socket) {
|
||||||
TcpConnection user = new TcpConnection(socket);
|
TcpConnection userConnection = new TcpConnection(socket);
|
||||||
|
|
||||||
// Receive user information
|
// Receive user information
|
||||||
user.receiveOne(o -> {
|
userConnection.receiveOne(o -> {
|
||||||
if (o instanceof UserInformation) {
|
if (o instanceof UserInformation) {
|
||||||
UserInformation userInformation = ((UserInformation) o);
|
UserInformation userInformation = ((UserInformation) o);
|
||||||
Log.v(getClass().getSimpleName(), "Registering user " + userInformation.id +
|
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
|
// 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
|
// 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));
|
e -> Log.e(getClass().getSimpleName(), "Error while receiving user information", e));
|
||||||
|
|
||||||
subscribers.put(userInformation.id, user);
|
adduser(userInformation, userConnection);
|
||||||
connectedUsers.add(userInformation);
|
|
||||||
|
|
||||||
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 -> {
|
e -> {
|
||||||
if (e instanceof EOFException) {
|
if (e instanceof EOFException) {
|
||||||
unsubscribe(userInformation);
|
unsubscribe(userInformation);
|
||||||
|
|
Loading…
Reference in a new issue