Compare commits
2 Commits
b653652f6d
...
f/fancy-di
Author | SHA1 | Date | |
---|---|---|---|
6b02fd0f46
|
|||
a062911d55 |
@ -21,6 +21,7 @@
|
|||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
<attribute name="module" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||||
|
@ -22,21 +22,20 @@ import envoy.client.net.WriteProxy;
|
|||||||
*/
|
*/
|
||||||
public class Chat implements Serializable {
|
public class Chat implements Serializable {
|
||||||
|
|
||||||
protected transient ObservableList<Message> messages = FXCollections.observableArrayList();
|
protected boolean disabled;
|
||||||
|
|
||||||
protected final Contact recipient;
|
|
||||||
|
|
||||||
protected boolean disabled;
|
|
||||||
protected boolean underlyingContactDeleted;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the last time an {@link envoy.event.IsTyping} event has been sent.
|
* Stores the last time an {@link envoy.event.IsTyping} event has been sent.
|
||||||
*/
|
*/
|
||||||
protected transient long lastWritingEvent;
|
protected transient long lastWritingEvent;
|
||||||
|
|
||||||
|
protected transient ObservableList<Message> messages = FXCollections.observableArrayList();
|
||||||
|
|
||||||
protected int unreadAmount;
|
protected int unreadAmount;
|
||||||
protected static IntegerProperty totalUnreadAmount = new SimpleIntegerProperty();
|
protected static IntegerProperty totalUnreadAmount = new SimpleIntegerProperty();
|
||||||
|
|
||||||
|
protected final Contact recipient;
|
||||||
|
|
||||||
private static final long serialVersionUID = 2L;
|
private static final long serialVersionUID = 2L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -248,10 +248,6 @@ public final class LocalDB implements EventListener {
|
|||||||
*/
|
*/
|
||||||
@Event(eventType = EnvoyCloseEvent.class, priority = 500)
|
@Event(eventType = EnvoyCloseEvent.class, priority = 500)
|
||||||
private synchronized void save() {
|
private synchronized void save() {
|
||||||
|
|
||||||
// Stop saving if this account has been deleted
|
|
||||||
if (userFile == null)
|
|
||||||
return;
|
|
||||||
EnvoyLog.getLogger(LocalDB.class).log(Level.FINER, "Saving local database...");
|
EnvoyLog.getLogger(LocalDB.class).log(Level.FINER, "Saving local database...");
|
||||||
|
|
||||||
// Save users
|
// Save users
|
||||||
@ -277,29 +273,6 @@ public final class LocalDB implements EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes any local remnant of this user.
|
|
||||||
*
|
|
||||||
* @since Envoy Client v0.3-beta
|
|
||||||
*/
|
|
||||||
public void delete() {
|
|
||||||
try {
|
|
||||||
|
|
||||||
// Save ID generator - can be used for other users in that db
|
|
||||||
if (hasIDGenerator())
|
|
||||||
SerializationUtils.write(idGeneratorFile, idGenerator);
|
|
||||||
} catch (final IOException e) {
|
|
||||||
EnvoyLog.getLogger(LocalDB.class).log(Level.SEVERE, "Unable to save local database: ",
|
|
||||||
e);
|
|
||||||
}
|
|
||||||
if (lastLoginFile != null)
|
|
||||||
lastLoginFile.delete();
|
|
||||||
userFile.delete();
|
|
||||||
users.remove(user.getName());
|
|
||||||
userFile = null;
|
|
||||||
onLogout();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Event(priority = 500)
|
@Event(priority = 500)
|
||||||
private void onMessage(Message msg) {
|
private void onMessage(Message msg) {
|
||||||
if (msg.getStatus() == MessageStatus.SENT)
|
if (msg.getStatus() == MessageStatus.SENT)
|
||||||
@ -431,14 +404,6 @@ public final class LocalDB implements EventListener {
|
|||||||
getChat(event.get().getID()).ifPresent(chat -> chat.setDisabled(true));
|
getChat(event.get().getID()).ifPresent(chat -> chat.setDisabled(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Event(priority = 500)
|
|
||||||
private void onAccountDeletion(AccountDeletion deletion) {
|
|
||||||
if (user.getID() == deletion.get())
|
|
||||||
logger.log(Level.WARNING,
|
|
||||||
"I have been informed by the server that I have been deleted without even knowing it...");
|
|
||||||
getChat(deletion.get()).ifPresent(chat -> chat.setDisabled(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a {@code Map<String, User>} of all users stored locally with their user names as keys
|
* @return a {@code Map<String, User>} of all users stored locally with their user names as keys
|
||||||
* @since Envoy Client v0.2-alpha
|
* @since Envoy Client v0.2-alpha
|
||||||
|
@ -6,7 +6,7 @@ import envoy.data.User.UserStatus;
|
|||||||
|
|
||||||
import envoy.client.data.Context;
|
import envoy.client.data.Context;
|
||||||
import envoy.client.helper.ShutdownHelper;
|
import envoy.client.helper.ShutdownHelper;
|
||||||
import envoy.client.ui.SceneInfo;
|
import envoy.client.ui.SceneContext.SceneInfo;
|
||||||
import envoy.client.util.UserUtil;
|
import envoy.client.util.UserUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,7 +4,7 @@ import java.util.*;
|
|||||||
|
|
||||||
import javafx.scene.input.KeyCombination;
|
import javafx.scene.input.KeyCombination;
|
||||||
|
|
||||||
import envoy.client.ui.SceneInfo;
|
import envoy.client.ui.SceneContext.SceneInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains all keyboard shortcuts used throughout the application.
|
* Contains all keyboard shortcuts used throughout the application.
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
package envoy.client.event;
|
|
||||||
|
|
||||||
import envoy.event.Event;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signifies the deletion of an account.
|
|
||||||
*
|
|
||||||
* @author Leon Hofmeister
|
|
||||||
* @since Envoy Common v0.3-beta
|
|
||||||
*/
|
|
||||||
public class AccountDeletion extends Event<Long> {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param value the ID of the contact that was deleted
|
|
||||||
* @since Envoy Common v0.3-beta
|
|
||||||
*/
|
|
||||||
public AccountDeletion(Long value) {
|
|
||||||
super(value);
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,6 +4,7 @@ import java.io.IOException;
|
|||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import javafx.application.Platform;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.*;
|
import javafx.scene.*;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
@ -27,11 +28,51 @@ import envoy.client.event.*;
|
|||||||
*/
|
*/
|
||||||
public final class SceneContext implements EventListener {
|
public final class SceneContext implements EventListener {
|
||||||
|
|
||||||
private final Stage stage;
|
/**
|
||||||
private final Stack<Parent> roots = new Stack<>();
|
* Contains information about different scenes and their FXML resource files.
|
||||||
private final Stack<Object> controllers = new Stack<>();
|
*
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
public enum SceneInfo {
|
||||||
|
|
||||||
private Scene scene;
|
/**
|
||||||
|
* The main scene in which the chat screen is displayed.
|
||||||
|
*
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
CHAT_SCENE("/fxml/ChatScene.fxml"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The scene in which the settings screen is displayed.
|
||||||
|
*
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
SETTINGS_SCENE("/fxml/SettingsScene.fxml"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The scene in which the login screen is displayed.
|
||||||
|
*
|
||||||
|
* @since Envoy Client v0.1-beta
|
||||||
|
*/
|
||||||
|
LOGIN_SCENE("/fxml/LoginScene.fxml");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the FXML resource.
|
||||||
|
*/
|
||||||
|
public final String path;
|
||||||
|
|
||||||
|
SceneInfo(String path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Stage stage;
|
||||||
|
private final FXMLLoader loader = new FXMLLoader();
|
||||||
|
private final Stack<Scene> sceneStack = new Stack<>();
|
||||||
|
private final Stack<Object> controllerStack = new Stack<>();
|
||||||
|
|
||||||
|
private static final Settings settings = Settings.getInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the scene context.
|
* Initializes the scene context.
|
||||||
@ -47,44 +88,44 @@ public final class SceneContext implements EventListener {
|
|||||||
/**
|
/**
|
||||||
* Loads a new scene specified by a scene info.
|
* Loads a new scene specified by a scene info.
|
||||||
*
|
*
|
||||||
* @param info specifies the scene to load
|
* @param sceneInfo specifies the scene to load
|
||||||
* @throws RuntimeException if the loading process fails
|
* @throws RuntimeException if the loading process fails
|
||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
*/
|
*/
|
||||||
public void load(SceneInfo info) {
|
public void load(SceneInfo sceneInfo) {
|
||||||
EnvoyLog.getLogger(SceneContext.class).log(Level.FINER, "Loading scene " + info);
|
EnvoyLog.getLogger(SceneContext.class).log(Level.FINER, "Loading scene " + sceneInfo);
|
||||||
|
loader.setRoot(null);
|
||||||
|
loader.setController(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
final var rootNode =
|
||||||
|
(Parent) loader.load(getClass().getResourceAsStream(sceneInfo.path));
|
||||||
|
final var scene = new Scene(rootNode);
|
||||||
|
final var controller = loader.getController();
|
||||||
|
controllerStack.push(controller);
|
||||||
|
|
||||||
// Load root node and controller
|
sceneStack.push(scene);
|
||||||
var loader = new FXMLLoader();
|
stage.setScene(scene);
|
||||||
Parent root = loader.load(getClass().getResourceAsStream(info.path));
|
|
||||||
Object controller = loader.getController();
|
|
||||||
roots.push(root);
|
|
||||||
controllers.push(controller);
|
|
||||||
|
|
||||||
if (scene == null) {
|
|
||||||
|
|
||||||
// One-time scene initialization
|
|
||||||
scene = new Scene(root, stage.getWidth(), stage.getHeight());
|
|
||||||
applyCSS();
|
|
||||||
stage.setScene(scene);
|
|
||||||
} else {
|
|
||||||
scene.setRoot(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove previous keyboard shortcuts
|
|
||||||
scene.getAccelerators().clear();
|
|
||||||
|
|
||||||
// Supply the global custom keyboard shortcuts for that scene
|
// Supply the global custom keyboard shortcuts for that scene
|
||||||
scene.getAccelerators()
|
scene.getAccelerators()
|
||||||
.putAll(GlobalKeyShortcuts.getInstance().getKeyboardShortcuts(info));
|
.putAll(GlobalKeyShortcuts.getInstance().getKeyboardShortcuts(sceneInfo));
|
||||||
|
|
||||||
// Supply the scene specific keyboard shortcuts
|
// Supply the scene specific keyboard shortcuts
|
||||||
if (controller instanceof KeyboardMapping)
|
if (controller instanceof KeyboardMapping)
|
||||||
scene.getAccelerators()
|
scene.getAccelerators()
|
||||||
.putAll(((KeyboardMapping) controller).getKeyboardShortcuts());
|
.putAll(((KeyboardMapping) controller).getKeyboardShortcuts());
|
||||||
} catch (IOException e) {
|
|
||||||
|
// The LoginScene is the only scene not intended to be resized
|
||||||
|
// As strange as it seems, this is needed as otherwise the LoginScene won't be
|
||||||
|
// displayed on some OS (...Debian...)
|
||||||
|
stage.sizeToScene();
|
||||||
|
Platform.runLater(() -> stage.setResizable(sceneInfo != SceneInfo.LOGIN_SCENE));
|
||||||
|
applyCSS();
|
||||||
|
stage.show();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
EnvoyLog.getLogger(SceneContext.class).log(Level.SEVERE,
|
||||||
|
String.format("Could not load scene for %s: ", sceneInfo), e);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,30 +137,29 @@ public final class SceneContext implements EventListener {
|
|||||||
*/
|
*/
|
||||||
public void pop() {
|
public void pop() {
|
||||||
|
|
||||||
// Pop current root node and controller
|
// Pop scene and controller
|
||||||
roots.pop();
|
sceneStack.pop();
|
||||||
controllers.pop();
|
controllerStack.pop();
|
||||||
|
|
||||||
// Apply new scene if present
|
// Apply new scene if present
|
||||||
if (!roots.isEmpty()) {
|
if (!sceneStack.isEmpty()) {
|
||||||
scene.setRoot(roots.peek());
|
final var newScene = sceneStack.peek();
|
||||||
|
stage.setScene(newScene);
|
||||||
// Invoke restore if controller is restorable
|
applyCSS();
|
||||||
var controller = controllers.peek();
|
stage.sizeToScene();
|
||||||
|
// If the controller implements the Restorable interface,
|
||||||
|
// the actions to perform on restoration will be executed here
|
||||||
|
final var controller = controllerStack.peek();
|
||||||
if (controller instanceof Restorable)
|
if (controller instanceof Restorable)
|
||||||
((Restorable) controller).onRestore();
|
((Restorable) controller).onRestore();
|
||||||
} else {
|
|
||||||
|
|
||||||
// Remove the current scene entirely
|
|
||||||
scene = null;
|
|
||||||
stage.setScene(null);
|
|
||||||
}
|
}
|
||||||
|
stage.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyCSS() {
|
private void applyCSS() {
|
||||||
if (scene != null) {
|
if (!sceneStack.isEmpty()) {
|
||||||
var styleSheets = scene.getStylesheets();
|
final var styleSheets = stage.getScene().getStylesheets();
|
||||||
var themeCSS = "/css/" + Settings.getInstance().getCurrentTheme() + ".css";
|
final var themeCSS = "/css/" + settings.getCurrentTheme() + ".css";
|
||||||
styleSheets.clear();
|
styleSheets.clear();
|
||||||
styleSheets.addAll(getClass().getResource("/css/base.css").toExternalForm(),
|
styleSheets.addAll(getClass().getResource("/css/base.css").toExternalForm(),
|
||||||
getClass().getResource(themeCSS).toExternalForm());
|
getClass().getResource(themeCSS).toExternalForm());
|
||||||
@ -128,8 +168,8 @@ public final class SceneContext implements EventListener {
|
|||||||
|
|
||||||
@Event(eventType = Logout.class, priority = 150)
|
@Event(eventType = Logout.class, priority = 150)
|
||||||
private void onLogout() {
|
private void onLogout() {
|
||||||
roots.clear();
|
sceneStack.clear();
|
||||||
controllers.clear();
|
controllerStack.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Event(priority = 150, eventType = ThemeChangeEvent.class)
|
@Event(priority = 150, eventType = ThemeChangeEvent.class)
|
||||||
@ -142,7 +182,7 @@ public final class SceneContext implements EventListener {
|
|||||||
* @return the controller used by the current scene
|
* @return the controller used by the current scene
|
||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
*/
|
*/
|
||||||
public <T> T getController() { return (T) controllers.peek(); }
|
public <T> T getController() { return (T) controllerStack.peek(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the stage in which the scenes are displayed
|
* @return the stage in which the scenes are displayed
|
||||||
@ -154,5 +194,5 @@ public final class SceneContext implements EventListener {
|
|||||||
* @return whether the scene stack is empty
|
* @return whether the scene stack is empty
|
||||||
* @since Envoy Client v0.2-beta
|
* @since Envoy Client v0.2-beta
|
||||||
*/
|
*/
|
||||||
public boolean isEmpty() { return roots.isEmpty(); }
|
public boolean isEmpty() { return sceneStack.isEmpty(); }
|
||||||
}
|
}
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
package envoy.client.ui;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains information about different scenes and their FXML resource files.
|
|
||||||
*
|
|
||||||
* @author Kai S. K. Engelbart
|
|
||||||
* @since Envoy Client v0.1-beta
|
|
||||||
*/
|
|
||||||
public enum SceneInfo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The main scene in which the chat screen is displayed.
|
|
||||||
*
|
|
||||||
* @since Envoy Client v0.1-beta
|
|
||||||
*/
|
|
||||||
CHAT_SCENE("/fxml/ChatScene.fxml"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The scene in which the settings screen is displayed.
|
|
||||||
*
|
|
||||||
* @since Envoy Client v0.1-beta
|
|
||||||
*/
|
|
||||||
SETTINGS_SCENE("/fxml/SettingsScene.fxml"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The scene in which the login screen is displayed.
|
|
||||||
*
|
|
||||||
* @since Envoy Client v0.1-beta
|
|
||||||
*/
|
|
||||||
LOGIN_SCENE("/fxml/LoginScene.fxml");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The path to the FXML resource.
|
|
||||||
*/
|
|
||||||
public final String path;
|
|
||||||
|
|
||||||
SceneInfo(String path) {
|
|
||||||
this.path = path;
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,6 +20,7 @@ import envoy.client.data.*;
|
|||||||
import envoy.client.data.shortcuts.EnvoyShortcutConfig;
|
import envoy.client.data.shortcuts.EnvoyShortcutConfig;
|
||||||
import envoy.client.helper.ShutdownHelper;
|
import envoy.client.helper.ShutdownHelper;
|
||||||
import envoy.client.net.Client;
|
import envoy.client.net.Client;
|
||||||
|
import envoy.client.ui.SceneContext.SceneInfo;
|
||||||
import envoy.client.ui.controller.LoginScene;
|
import envoy.client.ui.controller.LoginScene;
|
||||||
import envoy.client.util.IconUtil;
|
import envoy.client.util.IconUtil;
|
||||||
|
|
||||||
@ -93,7 +94,7 @@ public final class Startup extends Application {
|
|||||||
final var sceneContext = new SceneContext(stage);
|
final var sceneContext = new SceneContext(stage);
|
||||||
context.setSceneContext(sceneContext);
|
context.setSceneContext(sceneContext);
|
||||||
|
|
||||||
// Authenticate with token if present or load login scene
|
// Authenticate with token if present
|
||||||
if (localDB.getAuthToken() != null) {
|
if (localDB.getAuthToken() != null) {
|
||||||
logger.info("Attempting authentication with token...");
|
logger.info("Attempting authentication with token...");
|
||||||
localDB.loadUserData();
|
localDB.loadUserData();
|
||||||
@ -102,9 +103,8 @@ public final class Startup extends Application {
|
|||||||
VERSION, localDB.getLastSync())))
|
VERSION, localDB.getLastSync())))
|
||||||
sceneContext.load(SceneInfo.LOGIN_SCENE);
|
sceneContext.load(SceneInfo.LOGIN_SCENE);
|
||||||
} else
|
} else
|
||||||
|
// Load login scene
|
||||||
sceneContext.load(SceneInfo.LOGIN_SCENE);
|
sceneContext.load(SceneInfo.LOGIN_SCENE);
|
||||||
|
|
||||||
stage.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -226,7 +226,7 @@ public final class Startup extends Application {
|
|||||||
// Load ChatScene
|
// Load ChatScene
|
||||||
stage.setMinHeight(400);
|
stage.setMinHeight(400);
|
||||||
stage.setMinWidth(843);
|
stage.setMinWidth(843);
|
||||||
context.getSceneContext().load(SceneInfo.CHAT_SCENE);
|
context.getSceneContext().load(SceneContext.SceneInfo.CHAT_SCENE);
|
||||||
stage.centerOnScreen();
|
stage.centerOnScreen();
|
||||||
|
|
||||||
// Exit or minimize the stage when a close request occurs
|
// Exit or minimize the stage when a close request occurs
|
||||||
|
@ -15,7 +15,7 @@ import envoy.util.EnvoyLog;
|
|||||||
import envoy.client.data.Context;
|
import envoy.client.data.Context;
|
||||||
import envoy.client.data.commands.*;
|
import envoy.client.data.commands.*;
|
||||||
import envoy.client.helper.ShutdownHelper;
|
import envoy.client.helper.ShutdownHelper;
|
||||||
import envoy.client.ui.SceneInfo;
|
import envoy.client.ui.SceneContext.SceneInfo;
|
||||||
import envoy.client.ui.controller.ChatScene;
|
import envoy.client.ui.controller.ChatScene;
|
||||||
import envoy.client.util.*;
|
import envoy.client.util.*;
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ public final class ChatSceneCommands {
|
|||||||
private final SystemCommandBuilder builder =
|
private final SystemCommandBuilder builder =
|
||||||
new SystemCommandBuilder(messageTextAreaCommands);
|
new SystemCommandBuilder(messageTextAreaCommands);
|
||||||
|
|
||||||
private static final String messageDependentCommandDescription =
|
private static final String messageDependantCommandDescription =
|
||||||
" the given message. Use s/S to use the selected message. Otherwise expects a number relative to the uppermost completely visible message.";
|
" the given message. Use s/S to use the selected message. Otherwise expects a number relative to the uppermost completely visible message.";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -141,7 +141,7 @@ public final class ChatSceneCommands {
|
|||||||
else
|
else
|
||||||
useRelativeMessage(command, action, additionalCheck, positionalArgument, false);
|
useRelativeMessage(command, action, additionalCheck, positionalArgument, false);
|
||||||
}).setDefaults("s").setNumberOfArguments(1)
|
}).setDefaults("s").setNumberOfArguments(1)
|
||||||
.setDescription(description.concat(messageDependentCommandDescription)).build(command);
|
.setDescription(description.concat(messageDependantCommandDescription)).build(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void selectionNeighbor(Consumer<Message> action, Predicate<Message> additionalCheck,
|
private void selectionNeighbor(Consumer<Message> action, Predicate<Message> additionalCheck,
|
||||||
|
@ -18,7 +18,7 @@ import envoy.client.util.IconUtil;
|
|||||||
*/
|
*/
|
||||||
public final class ChatControl extends HBox {
|
public final class ChatControl extends HBox {
|
||||||
|
|
||||||
private static Image userIcon = IconUtil.loadIconThemeSensitive("user_icon", 32),
|
private static final Image userIcon = IconUtil.loadIconThemeSensitive("user_icon", 32),
|
||||||
groupIcon = IconUtil.loadIconThemeSensitive("group_icon", 32);
|
groupIcon = IconUtil.loadIconThemeSensitive("group_icon", 32);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,14 +60,4 @@ public final class ChatControl extends HBox {
|
|||||||
}
|
}
|
||||||
getStyleClass().add("list-element");
|
getStyleClass().add("list-element");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reloads the default icons.
|
|
||||||
*
|
|
||||||
* @since Envoy Client v0.3-beta
|
|
||||||
*/
|
|
||||||
public static void reloadDefaultChatIcons() {
|
|
||||||
userIcon = IconUtil.loadIconThemeSensitive("user_icon", 32);
|
|
||||||
groupIcon = IconUtil.loadIconThemeSensitive("group_icon", 32);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
package envoy.client.ui.controller;
|
package envoy.client.ui.controller;
|
||||||
|
|
||||||
import static envoy.client.ui.SceneInfo.SETTINGS_SCENE;
|
|
||||||
|
|
||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
import java.awt.datatransfer.StringSelection;
|
import java.awt.datatransfer.StringSelection;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
|
|
||||||
import javafx.animation.RotateTransition;
|
import javafx.animation.RotateTransition;
|
||||||
@ -40,7 +37,6 @@ import envoy.util.EnvoyLog;
|
|||||||
|
|
||||||
import envoy.client.data.*;
|
import envoy.client.data.*;
|
||||||
import envoy.client.data.audio.AudioRecorder;
|
import envoy.client.data.audio.AudioRecorder;
|
||||||
import envoy.client.data.shortcuts.KeyboardMapping;
|
|
||||||
import envoy.client.event.*;
|
import envoy.client.event.*;
|
||||||
import envoy.client.net.*;
|
import envoy.client.net.*;
|
||||||
import envoy.client.ui.*;
|
import envoy.client.ui.*;
|
||||||
@ -55,7 +51,7 @@ import envoy.client.util.*;
|
|||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
*/
|
*/
|
||||||
public final class ChatScene implements EventListener, Restorable, KeyboardMapping {
|
public final class ChatScene implements EventListener, Restorable {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private ListView<Message> messageList;
|
private ListView<Message> messageList;
|
||||||
@ -324,7 +320,6 @@ public final class ChatScene implements EventListener, Restorable, KeyboardMappi
|
|||||||
|
|
||||||
@Event(eventType = ThemeChangeEvent.class)
|
@Event(eventType = ThemeChangeEvent.class)
|
||||||
private void onThemeChange() {
|
private void onThemeChange() {
|
||||||
ChatControl.reloadDefaultChatIcons();
|
|
||||||
settingsButton.setGraphic(
|
settingsButton.setGraphic(
|
||||||
new ImageView(IconUtil.loadIconThemeSensitive("settings", DEFAULT_ICON_SIZE)));
|
new ImageView(IconUtil.loadIconThemeSensitive("settings", DEFAULT_ICON_SIZE)));
|
||||||
voiceButton.setGraphic(
|
voiceButton.setGraphic(
|
||||||
@ -351,11 +346,6 @@ public final class ChatScene implements EventListener, Restorable, KeyboardMappi
|
|||||||
eventBus.removeListener(this);
|
eventBus.removeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Event(eventType = AccountDeletion.class)
|
|
||||||
private void onAccountDeletion() {
|
|
||||||
Platform.runLater(chatList::refresh);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRestore() {
|
public void onRestore() {
|
||||||
updateRemainingCharsLabel();
|
updateRemainingCharsLabel();
|
||||||
@ -448,7 +438,7 @@ public final class ChatScene implements EventListener, Restorable, KeyboardMappi
|
|||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
private void settingsButtonClicked() {
|
private void settingsButtonClicked() {
|
||||||
sceneContext.load(SETTINGS_SCENE);
|
sceneContext.load(SceneContext.SceneInfo.SETTINGS_SCENE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -596,7 +586,7 @@ public final class ChatScene implements EventListener, Restorable, KeyboardMappi
|
|||||||
// IsTyping#millisecondsActive
|
// IsTyping#millisecondsActive
|
||||||
if (client.isOnline() && currentChat.getLastWritingEvent()
|
if (client.isOnline() && currentChat.getLastWritingEvent()
|
||||||
+ IsTyping.millisecondsActive <= System.currentTimeMillis()) {
|
+ IsTyping.millisecondsActive <= System.currentTimeMillis()) {
|
||||||
client.send(new IsTyping(currentChat.getRecipient().getID()));
|
client.send(new IsTyping(getChatID(), currentChat.getRecipient().getID()));
|
||||||
currentChat.lastWritingEventWasNow();
|
currentChat.lastWritingEventWasNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -610,6 +600,19 @@ public final class ChatScene implements EventListener, Restorable, KeyboardMappi
|
|||||||
checkPostConditions(false);
|
checkPostConditions(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the id that should be used to send things to the server: the id of 'our' {@link User}
|
||||||
|
* if the recipient of that object is another User, else the id of the {@link Group} 'our' user
|
||||||
|
* is sending to.
|
||||||
|
*
|
||||||
|
* @return an id that can be sent to the server
|
||||||
|
* @since Envoy Client v0.2-beta
|
||||||
|
*/
|
||||||
|
private long getChatID() {
|
||||||
|
return currentChat.getRecipient() instanceof User ? client.getSender().getID()
|
||||||
|
: currentChat.getRecipient().getID();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param e the keys that have been pressed
|
* @param e the keys that have been pressed
|
||||||
* @since Envoy Client v0.1-beta
|
* @since Envoy Client v0.1-beta
|
||||||
@ -881,25 +884,4 @@ public final class ChatScene implements EventListener, Restorable, KeyboardMappi
|
|||||||
: c -> c.getRecipient().getName().toLowerCase()
|
: c -> c.getRecipient().getName().toLowerCase()
|
||||||
.contains(contactSearch.getText().toLowerCase()));
|
.contains(contactSearch.getText().toLowerCase()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<KeyCombination, Runnable> getKeyboardShortcuts() {
|
|
||||||
return Map.<KeyCombination, Runnable>of(
|
|
||||||
|
|
||||||
// Delete text before the caret with "Control" + U
|
|
||||||
new KeyCodeCombination(KeyCode.U, KeyCombination.CONTROL_DOWN), () -> {
|
|
||||||
messageTextArea
|
|
||||||
.setText(
|
|
||||||
messageTextArea.getText().substring(messageTextArea.getCaretPosition()));
|
|
||||||
checkPostConditions(false);
|
|
||||||
|
|
||||||
// Delete text after the caret with "Control" + K
|
|
||||||
}, new KeyCodeCombination(KeyCode.K, KeyCombination.CONTROL_DOWN), () -> {
|
|
||||||
messageTextArea
|
|
||||||
.setText(
|
|
||||||
messageTextArea.getText().substring(0, messageTextArea.getCaretPosition()));
|
|
||||||
checkPostConditions(false);
|
|
||||||
messageTextArea.positionCaret(messageTextArea.getText().length());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,11 @@ import dev.kske.eventbus.*;
|
|||||||
|
|
||||||
import envoy.data.*;
|
import envoy.data.*;
|
||||||
import envoy.event.GroupCreation;
|
import envoy.event.GroupCreation;
|
||||||
import envoy.event.contact.*;
|
import envoy.event.contact.UserOperation;
|
||||||
import envoy.util.Bounds;
|
import envoy.util.Bounds;
|
||||||
|
|
||||||
import envoy.client.data.*;
|
import envoy.client.data.*;
|
||||||
import envoy.client.event.*;
|
import envoy.client.event.BackEvent;
|
||||||
import envoy.client.ui.control.*;
|
import envoy.client.ui.control.*;
|
||||||
import envoy.client.ui.listcell.ListCellFactory;
|
import envoy.client.ui.listcell.ListCellFactory;
|
||||||
|
|
||||||
@ -252,10 +252,4 @@ public class GroupCreationTab implements EventListener {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Event
|
|
||||||
private void onAccountDeletion(AccountDeletion deletion) {
|
|
||||||
final var deletedID = deletion.get();
|
|
||||||
Platform.runLater(() -> userList.getItems().removeIf(user -> (user.getID() == deletedID)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import javafx.scene.image.*;
|
|||||||
import javafx.scene.input.InputEvent;
|
import javafx.scene.input.InputEvent;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
import javafx.util.Duration;
|
|
||||||
|
|
||||||
import dev.kske.eventbus.EventBus;
|
import dev.kske.eventbus.EventBus;
|
||||||
|
|
||||||
@ -21,7 +20,7 @@ import envoy.event.*;
|
|||||||
import envoy.util.*;
|
import envoy.util.*;
|
||||||
|
|
||||||
import envoy.client.ui.control.ProfilePicImageView;
|
import envoy.client.ui.control.ProfilePicImageView;
|
||||||
import envoy.client.util.*;
|
import envoy.client.util.IconUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Leon Hofmeister
|
* @author Leon Hofmeister
|
||||||
@ -39,7 +38,6 @@ public final class UserSettingsPane extends OnlineOnlySettingsPane {
|
|||||||
private final PasswordField newPasswordField = new PasswordField();
|
private final PasswordField newPasswordField = new PasswordField();
|
||||||
private final PasswordField repeatNewPasswordField = new PasswordField();
|
private final PasswordField repeatNewPasswordField = new PasswordField();
|
||||||
private final Button saveButton = new Button("Save");
|
private final Button saveButton = new Button("Save");
|
||||||
private final Button deleteAccountButton = new Button("Delete Account (Locally)");
|
|
||||||
|
|
||||||
private static final EventBus eventBus = EventBus.getInstance();
|
private static final EventBus eventBus = EventBus.getInstance();
|
||||||
private static final Logger logger = EnvoyLog.getLogger(UserSettingsPane.class);
|
private static final Logger logger = EnvoyLog.getLogger(UserSettingsPane.class);
|
||||||
@ -114,19 +112,16 @@ public final class UserSettingsPane extends OnlineOnlySettingsPane {
|
|||||||
|
|
||||||
final PasswordField[] passwordFields =
|
final PasswordField[] passwordFields =
|
||||||
{ currentPasswordField, newPasswordField, repeatNewPasswordField };
|
{ currentPasswordField, newPasswordField, repeatNewPasswordField };
|
||||||
final EventHandler<? super InputEvent> passwordEntered =
|
final EventHandler<? super InputEvent> passwordEntered = e -> {
|
||||||
e -> {
|
newPassword =
|
||||||
newPassword =
|
newPasswordField.getText();
|
||||||
newPasswordField
|
validPassword = newPassword
|
||||||
.getText();
|
.equals(
|
||||||
validPassword =
|
repeatNewPasswordField
|
||||||
newPassword.equals(
|
.getText())
|
||||||
repeatNewPasswordField
|
&& !newPasswordField
|
||||||
.getText())
|
.getText().isBlank();
|
||||||
&& !newPasswordField
|
};
|
||||||
.getText()
|
|
||||||
.isBlank();
|
|
||||||
};
|
|
||||||
newPasswordField.setOnInputMethodTextChanged(passwordEntered);
|
newPasswordField.setOnInputMethodTextChanged(passwordEntered);
|
||||||
newPasswordField.setOnKeyTyped(passwordEntered);
|
newPasswordField.setOnKeyTyped(passwordEntered);
|
||||||
repeatNewPasswordField.setOnInputMethodTextChanged(passwordEntered);
|
repeatNewPasswordField.setOnInputMethodTextChanged(passwordEntered);
|
||||||
@ -142,21 +137,9 @@ public final class UserSettingsPane extends OnlineOnlySettingsPane {
|
|||||||
|
|
||||||
// Displaying the save button
|
// Displaying the save button
|
||||||
saveButton
|
saveButton
|
||||||
.setOnAction(e -> save(currentPasswordField.getText()));
|
.setOnAction(e -> save(client.getSender().getID(), currentPasswordField.getText()));
|
||||||
saveButton.setAlignment(Pos.BOTTOM_RIGHT);
|
saveButton.setAlignment(Pos.BOTTOM_RIGHT);
|
||||||
getChildren().add(saveButton);
|
getChildren().add(saveButton);
|
||||||
|
|
||||||
// Displaying the delete account button
|
|
||||||
deleteAccountButton.setAlignment(Pos.BASELINE_CENTER);
|
|
||||||
deleteAccountButton.setOnAction(e -> UserUtil.deleteAccount());
|
|
||||||
deleteAccountButton.setText("Delete Account (locally)");
|
|
||||||
deleteAccountButton.setPrefHeight(25);
|
|
||||||
deleteAccountButton.getStyleClass().clear();
|
|
||||||
deleteAccountButton.getStyleClass().add("danger-button");
|
|
||||||
final var tooltip = new Tooltip("Remote deletion is currently unsupported.");
|
|
||||||
tooltip.setShowDelay(Duration.millis(100));
|
|
||||||
deleteAccountButton.setTooltip(tooltip);
|
|
||||||
getChildren().add(deleteAccountButton);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -165,11 +148,11 @@ public final class UserSettingsPane extends OnlineOnlySettingsPane {
|
|||||||
* @param username the new username
|
* @param username the new username
|
||||||
* @since Envoy Client v0.2-beta
|
* @since Envoy Client v0.2-beta
|
||||||
*/
|
*/
|
||||||
private void save(String oldPassword) {
|
private void save(long userID, String oldPassword) {
|
||||||
|
|
||||||
// The profile pic was changed
|
// The profile pic was changed
|
||||||
if (profilePicChanged) {
|
if (profilePicChanged) {
|
||||||
final var profilePicChangeEvent = new ProfilePicChange(currentImageBytes);
|
final var profilePicChangeEvent = new ProfilePicChange(currentImageBytes, userID);
|
||||||
eventBus.dispatch(profilePicChangeEvent);
|
eventBus.dispatch(profilePicChangeEvent);
|
||||||
client.send(profilePicChangeEvent);
|
client.send(profilePicChangeEvent);
|
||||||
logger.log(Level.INFO, "The user just changed his profile pic.");
|
logger.log(Level.INFO, "The user just changed his profile pic.");
|
||||||
@ -178,7 +161,7 @@ public final class UserSettingsPane extends OnlineOnlySettingsPane {
|
|||||||
// The username was changed
|
// The username was changed
|
||||||
final var validContactName = Bounds.isValidContactName(newUsername);
|
final var validContactName = Bounds.isValidContactName(newUsername);
|
||||||
if (usernameChanged && validContactName) {
|
if (usernameChanged && validContactName) {
|
||||||
final var nameChangeEvent = new NameChange(client.getSender().getID(), newUsername);
|
final var nameChangeEvent = new NameChange(userID, newUsername);
|
||||||
eventBus.dispatch(nameChangeEvent);
|
eventBus.dispatch(nameChangeEvent);
|
||||||
client.send(nameChangeEvent);
|
client.send(nameChangeEvent);
|
||||||
logger.log(Level.INFO, "The user just changed his name to " + newUsername + ".");
|
logger.log(Level.INFO, "The user just changed his name to " + newUsername + ".");
|
||||||
@ -195,7 +178,7 @@ public final class UserSettingsPane extends OnlineOnlySettingsPane {
|
|||||||
|
|
||||||
// The password was changed
|
// The password was changed
|
||||||
if (validPassword) {
|
if (validPassword) {
|
||||||
client.send(new PasswordChangeRequest(newPassword, oldPassword));
|
client.send(new PasswordChangeRequest(newPassword, oldPassword, userID));
|
||||||
logger.log(Level.INFO, "The user just tried to change his password!");
|
logger.log(Level.INFO, "The user just tried to change his password!");
|
||||||
} else if (!(validPassword || newPassword.isBlank())) {
|
} else if (!(validPassword || newPassword.isBlank())) {
|
||||||
final var alert = new Alert(AlertType.ERROR);
|
final var alert = new Alert(AlertType.ERROR);
|
||||||
|
@ -2,7 +2,7 @@ package envoy.client.util;
|
|||||||
|
|
||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
|
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.Alert.AlertType;
|
import javafx.scene.control.Alert.AlertType;
|
||||||
|
|
||||||
import dev.kske.eventbus.EventBus;
|
import dev.kske.eventbus.EventBus;
|
||||||
@ -16,7 +16,7 @@ import envoy.util.EnvoyLog;
|
|||||||
import envoy.client.data.Context;
|
import envoy.client.data.Context;
|
||||||
import envoy.client.event.*;
|
import envoy.client.event.*;
|
||||||
import envoy.client.helper.*;
|
import envoy.client.helper.*;
|
||||||
import envoy.client.ui.SceneInfo;
|
import envoy.client.ui.SceneContext.SceneInfo;
|
||||||
import envoy.client.ui.controller.ChatScene;
|
import envoy.client.ui.controller.ChatScene;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -121,35 +121,4 @@ public final class UserUtil {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes anything pointing to this user, independent of client or server. Will do nothing if
|
|
||||||
* the client is currently offline.
|
|
||||||
*
|
|
||||||
* @since Envoy Client v0.3-beta
|
|
||||||
*/
|
|
||||||
public static void deleteAccount() {
|
|
||||||
|
|
||||||
// Show the first wall of defense, if not disabled by the user
|
|
||||||
final var outerAlert = new Alert(AlertType.CONFIRMATION);
|
|
||||||
outerAlert.setContentText(
|
|
||||||
"Are you sure you want to delete your account entirely? This action can seriously not be undone.");
|
|
||||||
outerAlert.setTitle("Delete Account?");
|
|
||||||
AlertHelper.confirmAction(outerAlert, () -> {
|
|
||||||
|
|
||||||
// Show the final wall of defense in every case
|
|
||||||
final var lastAlert = new Alert(AlertType.WARNING,
|
|
||||||
"Do you REALLY want to delete your account? Last Warning. Proceed?",
|
|
||||||
ButtonType.CANCEL, ButtonType.OK);
|
|
||||||
lastAlert.setTitle("Delete Account?");
|
|
||||||
lastAlert.showAndWait().filter(ButtonType.OK::equals).ifPresent(b2 -> {
|
|
||||||
|
|
||||||
// Delete the account
|
|
||||||
// TODO: Notify server of account deletion
|
|
||||||
context.getLocalDB().delete();
|
|
||||||
logger.log(Level.INFO, "The user just deleted his account. Goodbye.");
|
|
||||||
ShutdownHelper.exit(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -70,17 +70,6 @@
|
|||||||
-fx-text-fill: gray;
|
-fx-text-fill: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.danger-button {
|
|
||||||
-fx-background-color: red;
|
|
||||||
-fx-text-fill: white;
|
|
||||||
-fx-background-radius: 0.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.danger-button:hover {
|
|
||||||
-fx-scale-x: 1.05;
|
|
||||||
-fx-scale-y: 1.05;
|
|
||||||
}
|
|
||||||
|
|
||||||
.received-message {
|
.received-message {
|
||||||
-fx-alignment: center-left;
|
-fx-alignment: center-left;
|
||||||
-fx-background-radius: 1.3em;
|
-fx-background-radius: 1.3em;
|
||||||
|
@ -30,10 +30,6 @@
|
|||||||
-fx-background-color: black;
|
-fx-background-color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip {
|
|
||||||
-fx-text-fill: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
#login-input-field {
|
#login-input-field {
|
||||||
-fx-border-color: black;
|
-fx-border-color: black;
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
|
|
||||||
<GridPane maxHeight="-Infinity" maxWidth="-Infinity"
|
<GridPane maxHeight="-Infinity" maxWidth="-Infinity"
|
||||||
minHeight="400.0" minWidth="500.0"
|
minHeight="400.0" minWidth="500.0"
|
||||||
prefWidth="${screen.visualBounds.width}"
|
|
||||||
prefHeight="${screen.visualBounds.height}"
|
prefHeight="${screen.visualBounds.height}"
|
||||||
|
prefWidth="${screen.visualBounds.width}"
|
||||||
xmlns="http://javafx.com/javafx/11.0.1"
|
xmlns="http://javafx.com/javafx/11.0.1"
|
||||||
xmlns:fx="http://javafx.com/fxml/1"
|
xmlns:fx="http://javafx.com/fxml/1"
|
||||||
fx:controller="envoy.client.ui.controller.ChatScene">
|
fx:controller="envoy.client.ui.controller.ChatScene">
|
||||||
@ -57,7 +57,8 @@
|
|||||||
<content>
|
<content>
|
||||||
<AnchorPane minHeight="0.0" minWidth="0.0">
|
<AnchorPane minHeight="0.0" minWidth="0.0">
|
||||||
<children>
|
<children>
|
||||||
<VBox prefHeight="3000.0" prefWidth="316.0">
|
<VBox prefHeight="3000.0"
|
||||||
|
prefWidth="316.0">
|
||||||
<children>
|
<children>
|
||||||
<VBox id="search-panel" maxHeight="-Infinity"
|
<VBox id="search-panel" maxHeight="-Infinity"
|
||||||
minHeight="-Infinity" prefHeight="80.0" prefWidth="316.0">
|
minHeight="-Infinity" prefHeight="80.0" prefWidth="316.0">
|
||||||
@ -155,7 +156,8 @@
|
|||||||
<Insets left="15.0" top="5.0" right="10.0" />
|
<Insets left="15.0" top="5.0" right="10.0" />
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
</ImageView>
|
</ImageView>
|
||||||
<Region id="transparent-background" HBox.hgrow="ALWAYS" />
|
<Region id="transparent-background"
|
||||||
|
HBox.hgrow="ALWAYS" />
|
||||||
<Button fx:id="settingsButton" mnemonicParsing="false"
|
<Button fx:id="settingsButton" mnemonicParsing="false"
|
||||||
onAction="#settingsButtonClicked" prefHeight="30.0"
|
onAction="#settingsButtonClicked" prefHeight="30.0"
|
||||||
prefWidth="30.0" alignment="CENTER_RIGHT">
|
prefWidth="30.0" alignment="CENTER_RIGHT">
|
||||||
@ -163,7 +165,7 @@
|
|||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<HBox.margin>
|
<HBox.margin>
|
||||||
<Insets bottom="35.0" left="5.0" top="35.0" right="10.0" />
|
<Insets bottom="35.0" left="5.0" top="35.0" right="10.0"/>
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
</Button>
|
</Button>
|
||||||
</children>
|
</children>
|
||||||
|
@ -7,16 +7,11 @@
|
|||||||
<?import javafx.scene.layout.HBox?>
|
<?import javafx.scene.layout.HBox?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
|
|
||||||
<VBox alignment="TOP_RIGHT" maxHeight="-Infinity" minHeight="400.0"
|
<VBox alignment="TOP_RIGHT" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="envoy.client.ui.controller.SettingsScene">
|
||||||
minWidth="500.0" xmlns="http://javafx.com/javafx/11.0.1"
|
|
||||||
xmlns:fx="http://javafx.com/fxml/1"
|
|
||||||
fx:controller="envoy.client.ui.controller.SettingsScene">
|
|
||||||
<children>
|
<children>
|
||||||
<HBox prefHeight="389.0" prefWidth="600.0">
|
<HBox prefHeight="389.0" prefWidth="600.0">
|
||||||
<children>
|
<children>
|
||||||
<ListView id="message-list" fx:id="settingsList"
|
<ListView id="message-list" fx:id="settingsList" onMouseClicked="#settingsListClicked" prefHeight="200.0" prefWidth="200.0">
|
||||||
onMouseClicked="#settingsListClicked" prefHeight="200.0"
|
|
||||||
prefWidth="200.0">
|
|
||||||
<opaqueInsets>
|
<opaqueInsets>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</opaqueInsets>
|
</opaqueInsets>
|
||||||
@ -27,8 +22,7 @@
|
|||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</ListView>
|
</ListView>
|
||||||
<TitledPane fx:id="titledPane" collapsible="false"
|
<TitledPane fx:id="titledPane" collapsible="false" prefHeight="400.0" prefWidth="400.0">
|
||||||
prefHeight="400.0" prefWidth="400.0">
|
|
||||||
<HBox.margin>
|
<HBox.margin>
|
||||||
<Insets bottom="10.0" left="5.0" right="10.0" top="10.0" />
|
<Insets bottom="10.0" left="5.0" right="10.0" top="10.0" />
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
@ -38,8 +32,7 @@
|
|||||||
</TitledPane>
|
</TitledPane>
|
||||||
</children>
|
</children>
|
||||||
</HBox>
|
</HBox>
|
||||||
<Button defaultButton="true" mnemonicParsing="true"
|
<Button defaultButton="true" mnemonicParsing="true" onMouseClicked="#backButtonClicked" text="_Back">
|
||||||
onMouseClicked="#backButtonClicked" text="_Back">
|
|
||||||
<opaqueInsets>
|
<opaqueInsets>
|
||||||
<Insets />
|
<Insets />
|
||||||
</opaqueInsets>
|
</opaqueInsets>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package envoy.data;
|
package envoy.data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface should be used for any type supposed to be a {@link Message} attachment (i.e.
|
* This interface should be used for any type supposed to be a {@link Message} attachment (i.e.
|
||||||
@ -64,9 +63,9 @@ public final class Attachment implements Serializable {
|
|||||||
* @since Envoy Common v0.1-beta
|
* @since Envoy Common v0.1-beta
|
||||||
*/
|
*/
|
||||||
public Attachment(byte[] data, String name, AttachmentType type) {
|
public Attachment(byte[] data, String name, AttachmentType type) {
|
||||||
this.data = Objects.requireNonNull(data);
|
this.data = data;
|
||||||
this.name = Objects.requireNonNull(name);
|
this.name = name;
|
||||||
this.type = Objects.requireNonNull(type);
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,8 +29,8 @@ public abstract class Contact implements Serializable {
|
|||||||
*/
|
*/
|
||||||
public Contact(long id, String name, Set<? extends Contact> contacts) {
|
public Contact(long id, String name, Set<? extends Contact> contacts) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = Objects.requireNonNull(name);
|
this.name = name;
|
||||||
this.contacts = contacts == null ? new HashSet<>() : contacts;
|
this.contacts = contacts;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,8 +38,7 @@ public final class GroupMessage extends Message {
|
|||||||
Map<Long, MessageStatus> memberStatuses) {
|
Map<Long, MessageStatus> memberStatuses) {
|
||||||
super(id, senderID, groupID, creationDate, receivedDate, readDate, text, attachment, status,
|
super(id, senderID, groupID, creationDate, receivedDate, readDate, text, attachment, status,
|
||||||
forwarded);
|
forwarded);
|
||||||
this.memberStatuses =
|
this.memberStatuses = memberStatuses;
|
||||||
memberStatuses == null ? new HashMap<>() : memberStatuses;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,7 +2,6 @@ package envoy.data;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains a {@link User}'s login / registration information as well as the client version.
|
* Contains a {@link User}'s login / registration information as well as the client version.
|
||||||
@ -21,14 +20,15 @@ public final class LoginCredentials implements Serializable {
|
|||||||
private static final long serialVersionUID = 4;
|
private static final long serialVersionUID = 4;
|
||||||
|
|
||||||
private LoginCredentials(String identifier, String password, boolean registration,
|
private LoginCredentials(String identifier, String password, boolean registration,
|
||||||
boolean token, boolean requestToken, String clientVersion, Instant lastSync) {
|
boolean token, boolean requestToken, String clientVersion,
|
||||||
this.identifier = Objects.requireNonNull(identifier);
|
Instant lastSync) {
|
||||||
this.password = Objects.requireNonNull(password);
|
this.identifier = identifier;
|
||||||
|
this.password = password;
|
||||||
this.registration = registration;
|
this.registration = registration;
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.requestToken = requestToken;
|
this.requestToken = requestToken;
|
||||||
this.clientVersion = Objects.requireNonNull(clientVersion);
|
this.clientVersion = clientVersion;
|
||||||
this.lastSync = lastSync == null ? Instant.EPOCH : lastSync;
|
this.lastSync = lastSync;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,8 +75,7 @@ public final class LoginCredentials implements Serializable {
|
|||||||
* @since Envoy Common v0.2-beta
|
* @since Envoy Common v0.2-beta
|
||||||
*/
|
*/
|
||||||
public static LoginCredentials registration(String identifier, String password,
|
public static LoginCredentials registration(String identifier, String password,
|
||||||
boolean requestToken,
|
boolean requestToken, String clientVersion, Instant lastSync) {
|
||||||
String clientVersion, Instant lastSync) {
|
|
||||||
return new LoginCredentials(identifier, password, true, false, requestToken, clientVersion,
|
return new LoginCredentials(identifier, password, true, false, requestToken, clientVersion,
|
||||||
lastSync);
|
lastSync);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package envoy.data;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import dev.kske.eventbus.IEvent;
|
import dev.kske.eventbus.IEvent;
|
||||||
|
|
||||||
@ -81,9 +80,9 @@ public class Message implements Serializable, IEvent {
|
|||||||
this.creationDate = creationDate;
|
this.creationDate = creationDate;
|
||||||
this.receivedDate = receivedDate;
|
this.receivedDate = receivedDate;
|
||||||
this.readDate = readDate;
|
this.readDate = readDate;
|
||||||
this.text = text == null ? "" : text;
|
this.text = text;
|
||||||
this.attachment = attachment;
|
this.attachment = attachment;
|
||||||
this.status = Objects.requireNonNull(status);
|
this.status = status;
|
||||||
this.forwarded = forwarded;
|
this.forwarded = forwarded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ public final class User extends Contact {
|
|||||||
*/
|
*/
|
||||||
public User(long id, String name, UserStatus status, Set<Contact> contacts) {
|
public User(long id, String name, UserStatus status, Set<Contact> contacts) {
|
||||||
super(id, name, contacts);
|
super(id, name, contacts);
|
||||||
this.status = Objects.requireNonNull(status);
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package envoy.event;
|
package envoy.event;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import dev.kske.eventbus.IEvent;
|
import dev.kske.eventbus.IEvent;
|
||||||
|
|
||||||
@ -21,16 +20,7 @@ public abstract class Event<T> implements IEvent, Serializable {
|
|||||||
private static final long serialVersionUID = 0L;
|
private static final long serialVersionUID = 0L;
|
||||||
|
|
||||||
protected Event(T value) {
|
protected Event(T value) {
|
||||||
this(value, false);
|
this.value = value;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This constructor is reserved for {@link Valueless} events. No other event should contain null
|
|
||||||
* values. Only use if really necessary. Using this constructor with {@code true} implies that
|
|
||||||
* the user has to manually check if the value of the event is null.
|
|
||||||
*/
|
|
||||||
protected Event(T value, boolean canBeNull) {
|
|
||||||
this.value = canBeNull ? value : Objects.requireNonNull(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,7 +46,7 @@ public abstract class Event<T> implements IEvent, Serializable {
|
|||||||
private static final long serialVersionUID = 0L;
|
private static final long serialVersionUID = 0L;
|
||||||
|
|
||||||
protected Valueless() {
|
protected Valueless() {
|
||||||
super(null, true);
|
super(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -20,7 +20,7 @@ public class GroupCreationResult extends Event<Group> {
|
|||||||
* @since Envoy Common v0.2-beta
|
* @since Envoy Common v0.2-beta
|
||||||
*/
|
*/
|
||||||
public GroupCreationResult() {
|
public GroupCreationResult() {
|
||||||
super(null, true);
|
super(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,7 +30,7 @@ public final class GroupMessageStatusChange extends MessageStatusChange {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the ID of the sender of this event
|
* @return the memberID which the user who sends this event has
|
||||||
* @since Envoy Common v0.1-beta
|
* @since Envoy Common v0.1-beta
|
||||||
*/
|
*/
|
||||||
public long getMemberID() { return memberID; }
|
public long getMemberID() { return memberID; }
|
||||||
|
@ -2,8 +2,6 @@ package envoy.event;
|
|||||||
|
|
||||||
import static envoy.event.ElementOperation.*;
|
import static envoy.event.ElementOperation.*;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import envoy.data.*;
|
import envoy.data.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,7 +30,7 @@ public final class GroupResize extends Event<User> {
|
|||||||
*/
|
*/
|
||||||
public GroupResize(User user, Group group, ElementOperation operation) {
|
public GroupResize(User user, Group group, ElementOperation operation) {
|
||||||
super(user);
|
super(user);
|
||||||
this.operation = Objects.requireNonNull(operation);
|
this.operation = operation;
|
||||||
final var contained = group.getContacts().contains(user);
|
final var contained = group.getContacts().contains(user);
|
||||||
if (contained && operation.equals(ADD))
|
if (contained && operation.equals(ADD))
|
||||||
throw new IllegalArgumentException(String.format("Cannot add %s to %s!", user, group));
|
throw new IllegalArgumentException(String.format("Cannot add %s to %s!", user, group));
|
||||||
|
@ -8,6 +8,8 @@ package envoy.event;
|
|||||||
*/
|
*/
|
||||||
public final class IsTyping extends Event<Long> {
|
public final class IsTyping extends Event<Long> {
|
||||||
|
|
||||||
|
private final long destinationID;
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,13 +22,20 @@ public final class IsTyping extends Event<Long> {
|
|||||||
public static final int millisecondsActive = 3500;
|
public static final int millisecondsActive = 3500;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@code IsTyping}. The client will only send the contact that should receive
|
* Creates a new {@code IsTyping} event with originator and recipient.
|
||||||
* this event. The server will send the id of the contact who sent this event.
|
|
||||||
*
|
*
|
||||||
* @param id the ID of the recipient (client)/ originator(server)
|
* @param sourceID the ID of the originator
|
||||||
|
* @param destinationID the ID of the contact the user wrote to
|
||||||
* @since Envoy Common v0.2-beta
|
* @since Envoy Common v0.2-beta
|
||||||
*/
|
*/
|
||||||
public IsTyping(long id) {
|
public IsTyping(Long sourceID, long destinationID) {
|
||||||
super(id);
|
super(sourceID);
|
||||||
|
this.destinationID = destinationID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the ID of the contact in whose chat the user typed something
|
||||||
|
* @since Envoy Common v0.2-beta
|
||||||
|
*/
|
||||||
|
public long getDestinationID() { return destinationID; }
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ public final class IssueProposal extends Event<String> {
|
|||||||
*/
|
*/
|
||||||
public IssueProposal(String title, String description, boolean isBug) {
|
public IssueProposal(String title, String description, boolean isBug) {
|
||||||
super(escape(title));
|
super(escape(title));
|
||||||
this.description = description == null ? "" : sanitizeDescription(description);
|
this.description = sanitizeDescription(description);
|
||||||
bug = isBug;
|
bug = isBug;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,8 +37,8 @@ public final class IssueProposal extends Event<String> {
|
|||||||
*/
|
*/
|
||||||
public IssueProposal(String title, String description, String user, boolean isBug) {
|
public IssueProposal(String title, String description, String user, boolean isBug) {
|
||||||
super(escape(title));
|
super(escape(title));
|
||||||
this.description = description == null ? ""
|
this.description =
|
||||||
: sanitizeDescription(description) + String.format("<br>Submitted by user %s.", user);
|
sanitizeDescription(description) + String.format("<br>Submitted by user %s.", user);
|
||||||
bug = isBug;
|
bug = isBug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package envoy.event;
|
package envoy.event;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import envoy.data.Message;
|
import envoy.data.Message;
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ public class MessageStatusChange extends Event<Message.MessageStatus> {
|
|||||||
public MessageStatusChange(long id, Message.MessageStatus status, Instant date) {
|
public MessageStatusChange(long id, Message.MessageStatus status, Instant date) {
|
||||||
super(status);
|
super(status);
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.date = Objects.requireNonNull(date);
|
this.date = date;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package envoy.event;
|
package envoy.event;
|
||||||
|
|
||||||
import java.util.Objects;
|
import envoy.data.Contact;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Leon Hofmeister
|
* @author Leon Hofmeister
|
||||||
@ -8,20 +8,29 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
public final class PasswordChangeRequest extends Event<String> {
|
public final class PasswordChangeRequest extends Event<String> {
|
||||||
|
|
||||||
private final String oldPassword;
|
private final long id;
|
||||||
|
private final String oldPassword;
|
||||||
|
|
||||||
private static final long serialVersionUID = 0L;
|
private static final long serialVersionUID = 0L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param newPassword the new password of that user
|
* @param newPassword the new password of that user
|
||||||
* @param oldPassword the old password of that user
|
* @param oldPassword the old password of that user
|
||||||
|
* @param userID the ID of the user who wants to change his password
|
||||||
* @since Envoy Common v0.2-beta
|
* @since Envoy Common v0.2-beta
|
||||||
*/
|
*/
|
||||||
public PasswordChangeRequest(String newPassword, String oldPassword) {
|
public PasswordChangeRequest(String newPassword, String oldPassword, long userID) {
|
||||||
super(newPassword);
|
super(newPassword);
|
||||||
this.oldPassword = Objects.requireNonNull(oldPassword);
|
this.oldPassword = oldPassword;
|
||||||
|
id = userID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the ID of the {@link Contact} this event is related to
|
||||||
|
* @since Envoy Common v0.2-alpha
|
||||||
|
*/
|
||||||
|
public long getID() { return id; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the old password of the underlying user
|
* @return the old password of the underlying user
|
||||||
* @since Envoy Common v0.2-beta
|
* @since Envoy Common v0.2-beta
|
||||||
@ -30,6 +39,6 @@ public final class PasswordChangeRequest extends Event<String> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "PasswordChangeRequest[]";
|
return "PasswordChangeRequest[id=" + id + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,23 @@ package envoy.event;
|
|||||||
*/
|
*/
|
||||||
public final class ProfilePicChange extends Event<byte[]> {
|
public final class ProfilePicChange extends Event<byte[]> {
|
||||||
|
|
||||||
|
private final long id;
|
||||||
|
|
||||||
private static final long serialVersionUID = 0L;
|
private static final long serialVersionUID = 0L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param value the byte[] of the new image
|
* @param value the byte[] of the new image
|
||||||
|
* @param userID the ID of the user who changed his profile pic
|
||||||
* @since Envoy Common v0.2-beta
|
* @since Envoy Common v0.2-beta
|
||||||
*/
|
*/
|
||||||
public ProfilePicChange(byte[] value) {
|
public ProfilePicChange(byte[] value, long userID) {
|
||||||
super(value);
|
super(value);
|
||||||
|
id = userID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the ID of the user changing his profile pic
|
||||||
|
* @since Envoy Common v0.2-beta
|
||||||
|
*/
|
||||||
|
public long getId() { return id; }
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package envoy.event.contact;
|
package envoy.event.contact;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import envoy.data.User;
|
import envoy.data.User;
|
||||||
import envoy.event.*;
|
import envoy.event.*;
|
||||||
|
|
||||||
@ -26,7 +24,7 @@ public final class UserOperation extends Event<User> {
|
|||||||
*/
|
*/
|
||||||
public UserOperation(User contact, ElementOperation operationType) {
|
public UserOperation(User contact, ElementOperation operationType) {
|
||||||
super(contact);
|
super(contact);
|
||||||
this.operationType = Objects.requireNonNull(operationType);
|
this.operationType = operationType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
285
doc/datamodel.uxf
Normal file
285
doc/datamodel.uxf
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<diagram program="umlet" version="14.3.0">
|
||||||
|
<zoom_level>10</zoom_level>
|
||||||
|
<element>
|
||||||
|
<id>UMLClass</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>50</x>
|
||||||
|
<y>60</y>
|
||||||
|
<w>210</w>
|
||||||
|
<h>240</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>DBUser
|
||||||
|
--
|
||||||
|
id: Long
|
||||||
|
nick: String
|
||||||
|
name: String
|
||||||
|
chats: Set<DBChat>
|
||||||
|
status: UserStatus
|
||||||
|
created: Instant
|
||||||
|
lastSeen: Instant
|
||||||
|
deleted: Boolean
|
||||||
|
avatar: DBAvatar
|
||||||
|
passwordHash: String
|
||||||
|
authToken: String
|
||||||
|
authTokenExpiration: Instant
|
||||||
|
--
|
||||||
|
+toCommon(): User</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLClass</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>380</x>
|
||||||
|
<y>330</y>
|
||||||
|
<w>290</w>
|
||||||
|
<h>160</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>DBMessage
|
||||||
|
--
|
||||||
|
id: Long
|
||||||
|
sender: DBUser
|
||||||
|
forwarded: Boolean
|
||||||
|
deleted: Boolean
|
||||||
|
statuses: Map<DBUser, DBMessageStatus>
|
||||||
|
text: String
|
||||||
|
attachment: DBAttachment
|
||||||
|
--
|
||||||
|
+toCommon(): Message</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLClass</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>770</x>
|
||||||
|
<y>320</y>
|
||||||
|
<w>210</w>
|
||||||
|
<h>100</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>DBMessageStatus
|
||||||
|
--
|
||||||
|
id: Long
|
||||||
|
status: MessageStatus
|
||||||
|
timestamp: Instant
|
||||||
|
--
|
||||||
|
+toCommon(): MessageStatus</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLClass</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>770</x>
|
||||||
|
<y>440</y>
|
||||||
|
<w>180</w>
|
||||||
|
<h>120</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>DBAttachment
|
||||||
|
--
|
||||||
|
id: Long
|
||||||
|
name: String
|
||||||
|
type: AttachmentType
|
||||||
|
url: String
|
||||||
|
--
|
||||||
|
+toCommon(): Attachment</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLClass</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>510</x>
|
||||||
|
<y>70</y>
|
||||||
|
<w>200</w>
|
||||||
|
<h>180</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>DBChat
|
||||||
|
--
|
||||||
|
id: Long
|
||||||
|
name: String
|
||||||
|
members: Set<DBUser>
|
||||||
|
admins: Set<DBUser>
|
||||||
|
messages: Set<DBMessage>
|
||||||
|
avatar: DBAvatar
|
||||||
|
allowJoining: Boolean
|
||||||
|
allowAttachments: Boolean
|
||||||
|
--
|
||||||
|
+toCommon(): Chat</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>250</x>
|
||||||
|
<y>100</y>
|
||||||
|
<w>280</w>
|
||||||
|
<h>40</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<->
|
||||||
|
m1=0..n
|
||||||
|
m2=0..n</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;260.0;10.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>600</x>
|
||||||
|
<y>240</y>
|
||||||
|
<w>50</w>
|
||||||
|
<h>110</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=->
|
||||||
|
m2=0..n</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;10.0;90.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>660</x>
|
||||||
|
<y>360</y>
|
||||||
|
<w>130</w>
|
||||||
|
<h>40</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=->
|
||||||
|
m2=0..n</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;110.0;10.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>660</x>
|
||||||
|
<y>470</y>
|
||||||
|
<w>130</w>
|
||||||
|
<h>40</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=->
|
||||||
|
m2=0..1</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;110.0;10.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>140</x>
|
||||||
|
<y>290</y>
|
||||||
|
<w>260</w>
|
||||||
|
<h>150</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<-
|
||||||
|
m1=0..n</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;10.0;130.0;240.0;130.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLPackage</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>10</x>
|
||||||
|
<y>0</y>
|
||||||
|
<w>1010</w>
|
||||||
|
<h>590</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>envoy.server.data
|
||||||
|
--
|
||||||
|
bg=#CCCCCC</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLClass</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>90</x>
|
||||||
|
<y>680</y>
|
||||||
|
<w>170</w>
|
||||||
|
<h>130</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>User
|
||||||
|
--
|
||||||
|
id: long
|
||||||
|
nick: String
|
||||||
|
name: String
|
||||||
|
status: UserStatus
|
||||||
|
created: Instant
|
||||||
|
deleted: boolean</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLClass</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>340</x>
|
||||||
|
<y>680</y>
|
||||||
|
<w>190</w>
|
||||||
|
<h>100</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>UserStatus
|
||||||
|
--
|
||||||
|
_+ONLINE: UserStatus_
|
||||||
|
_+AWAY: UserStatus_
|
||||||
|
_+BUSY: UserStatus_
|
||||||
|
_+OFFLINE: UserStatus_</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>250</x>
|
||||||
|
<y>730</y>
|
||||||
|
<w>110</w>
|
||||||
|
<h>30</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<-</panel_attributes>
|
||||||
|
<additional_attributes>90.0;10.0;10.0;10.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLClass</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>340</x>
|
||||||
|
<y>150</y>
|
||||||
|
<w>100</w>
|
||||||
|
<h>80</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>DBAvatar
|
||||||
|
--
|
||||||
|
id: Long
|
||||||
|
edited: Instant
|
||||||
|
url: String
|
||||||
|
layer=1</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>250</x>
|
||||||
|
<y>190</y>
|
||||||
|
<w>110</w>
|
||||||
|
<h>40</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<-
|
||||||
|
m1=0..1</panel_attributes>
|
||||||
|
<additional_attributes>90.0;10.0;10.0;10.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>430</x>
|
||||||
|
<y>190</y>
|
||||||
|
<w>100</w>
|
||||||
|
<h>40</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<-
|
||||||
|
m1=0..1</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;80.0;10.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLClass</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>610</x>
|
||||||
|
<y>680</y>
|
||||||
|
<w>180</w>
|
||||||
|
<h>130</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>Chat
|
||||||
|
--
|
||||||
|
id: long
|
||||||
|
name: String
|
||||||
|
deceased: boolean
|
||||||
|
members: Set<User>
|
||||||
|
admins: Set<User>
|
||||||
|
messages: List<Message></panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
</diagram>
|
501
doc/handshake_sequence_uml.uxf
Normal file
501
doc/handshake_sequence_uml.uxf
Normal file
@ -0,0 +1,501 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<diagram program="umlet" version="14.3.0">
|
||||||
|
<zoom_level>9</zoom_level>
|
||||||
|
<element>
|
||||||
|
<id>UMLActor</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>72</x>
|
||||||
|
<y>540</y>
|
||||||
|
<w>54</w>
|
||||||
|
<h>99</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>Client1</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>2196</x>
|
||||||
|
<y>504</y>
|
||||||
|
<w>198</w>
|
||||||
|
<h>171</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>Database
|
||||||
|
halign=center
|
||||||
|
bg=orange
|
||||||
|
--</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>351</x>
|
||||||
|
<y>513</y>
|
||||||
|
<w>90</w>
|
||||||
|
<h>117</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>Main</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>531</x>
|
||||||
|
<y>513</y>
|
||||||
|
<w>90</w>
|
||||||
|
<h>117</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>Startup
|
||||||
|
bg=orange</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>702</x>
|
||||||
|
<y>513</y>
|
||||||
|
<w>90</w>
|
||||||
|
<h>117</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>Client
|
||||||
|
bg=yellow</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>873</x>
|
||||||
|
<y>513</y>
|
||||||
|
<w>90</w>
|
||||||
|
<h>117</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>LocalDB
|
||||||
|
bg=pink</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1548</x>
|
||||||
|
<y>522</y>
|
||||||
|
<w>189</w>
|
||||||
|
<h>117</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>LoginCredentialsProcessor
|
||||||
|
bg=cyan</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1809</x>
|
||||||
|
<y>522</y>
|
||||||
|
<w>135</w>
|
||||||
|
<h>117</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>PersistenceManager
|
||||||
|
bg=gray</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>396</x>
|
||||||
|
<y>729</y>
|
||||||
|
<w>189</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<<-
|
||||||
|
start javaFX app</panel_attributes>
|
||||||
|
<additional_attributes>190.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>387</x>
|
||||||
|
<y>720</y>
|
||||||
|
<w>18</w>
|
||||||
|
<h>54</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes/>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>387</x>
|
||||||
|
<y>621</y>
|
||||||
|
<w>27</w>
|
||||||
|
<h>117</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=.</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;10.0;110.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>567</x>
|
||||||
|
<y>621</y>
|
||||||
|
<w>27</w>
|
||||||
|
<h>117</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=.</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;10.0;110.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>738</x>
|
||||||
|
<y>621</y>
|
||||||
|
<w>27</w>
|
||||||
|
<h>216</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=.</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;10.0;220.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>909</x>
|
||||||
|
<y>621</y>
|
||||||
|
<w>27</w>
|
||||||
|
<h>153</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=.</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;10.0;150.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>567</x>
|
||||||
|
<y>720</y>
|
||||||
|
<w>18</w>
|
||||||
|
<h>396</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>bg=orange</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>738</x>
|
||||||
|
<y>819</y>
|
||||||
|
<w>18</w>
|
||||||
|
<h>558</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>bg=yellow</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>909</x>
|
||||||
|
<y>756</y>
|
||||||
|
<w>18</w>
|
||||||
|
<h>621</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>bg=pink</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>576</x>
|
||||||
|
<y>756</y>
|
||||||
|
<w>351</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<<-
|
||||||
|
initialize</panel_attributes>
|
||||||
|
<additional_attributes>370.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1062</x>
|
||||||
|
<y>513</y>
|
||||||
|
<w>90</w>
|
||||||
|
<h>117</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>Receiver
|
||||||
|
bg=red</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1098</x>
|
||||||
|
<y>621</y>
|
||||||
|
<w>27</w>
|
||||||
|
<h>270</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=.</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;10.0;280.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1098</x>
|
||||||
|
<y>873</y>
|
||||||
|
<w>18</w>
|
||||||
|
<h>504</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>bg=red</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>576</x>
|
||||||
|
<y>1071</y>
|
||||||
|
<w>180</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<<-
|
||||||
|
init receivers
|
||||||
|
layer=0</panel_attributes>
|
||||||
|
<additional_attributes>180.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>576</x>
|
||||||
|
<y>828</y>
|
||||||
|
<w>180</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<<-
|
||||||
|
perform handshake</panel_attributes>
|
||||||
|
<additional_attributes>180.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>747</x>
|
||||||
|
<y>873</y>
|
||||||
|
<w>369</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<<-
|
||||||
|
init handhake receivers
|
||||||
|
layer=0</panel_attributes>
|
||||||
|
<additional_attributes>390.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>747</x>
|
||||||
|
<y>1071</y>
|
||||||
|
<w>369</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<<-
|
||||||
|
init permanent receivers
|
||||||
|
layer=0</panel_attributes>
|
||||||
|
<additional_attributes>390.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1638</x>
|
||||||
|
<y>630</y>
|
||||||
|
<w>27</w>
|
||||||
|
<h>306</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=.</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;10.0;320.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1638</x>
|
||||||
|
<y>918</y>
|
||||||
|
<w>18</w>
|
||||||
|
<h>558</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>bg=cyan</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>747</x>
|
||||||
|
<y>918</y>
|
||||||
|
<w>909</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<<-
|
||||||
|
send login credentials
|
||||||
|
layer=0</panel_attributes>
|
||||||
|
<additional_attributes>990.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1872</x>
|
||||||
|
<y>630</y>
|
||||||
|
<w>27</w>
|
||||||
|
<h>306</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=.</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;10.0;320.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1872</x>
|
||||||
|
<y>918</y>
|
||||||
|
<w>18</w>
|
||||||
|
<h>558</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>bg=gray</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1881</x>
|
||||||
|
<y>918</y>
|
||||||
|
<w>423</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<<-
|
||||||
|
use queries
|
||||||
|
layer=0</panel_attributes>
|
||||||
|
<additional_attributes>450.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>2286</x>
|
||||||
|
<y>666</y>
|
||||||
|
<w>27</w>
|
||||||
|
<h>270</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=.</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;10.0;280.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>2286</x>
|
||||||
|
<y>918</y>
|
||||||
|
<w>18</w>
|
||||||
|
<h>558</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>bg=orange</panel_attributes>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1647</x>
|
||||||
|
<y>918</y>
|
||||||
|
<w>243</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=<<-
|
||||||
|
aquire data
|
||||||
|
layer=0</panel_attributes>
|
||||||
|
<additional_attributes>250.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1881</x>
|
||||||
|
<y>954</y>
|
||||||
|
<w>423</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=->>
|
||||||
|
send query responses
|
||||||
|
layer=0</panel_attributes>
|
||||||
|
<additional_attributes>450.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1647</x>
|
||||||
|
<y>954</y>
|
||||||
|
<w>243</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=->>
|
||||||
|
send aquired data
|
||||||
|
layer=0</panel_attributes>
|
||||||
|
<additional_attributes>250.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>1107</x>
|
||||||
|
<y>990</y>
|
||||||
|
<w>549</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=->>
|
||||||
|
send user, chats, pending messages, etc.
|
||||||
|
layer=0</panel_attributes>
|
||||||
|
<additional_attributes>590.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>918</x>
|
||||||
|
<y>990</y>
|
||||||
|
<w>198</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=->>
|
||||||
|
store data
|
||||||
|
layer=0</panel_attributes>
|
||||||
|
<additional_attributes>200.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>99</x>
|
||||||
|
<y>729</y>
|
||||||
|
<w>306</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=->
|
||||||
|
start app</panel_attributes>
|
||||||
|
<additional_attributes>10.0;20.0;320.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>90</x>
|
||||||
|
<y>621</y>
|
||||||
|
<w>27</w>
|
||||||
|
<h>117</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=.</panel_attributes>
|
||||||
|
<additional_attributes>10.0;10.0;10.0;110.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>UMLGeneric</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>90</x>
|
||||||
|
<y>720</y>
|
||||||
|
<w>18</w>
|
||||||
|
<h>54</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes/>
|
||||||
|
<additional_attributes/>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<id>Relation</id>
|
||||||
|
<coordinates>
|
||||||
|
<x>747</x>
|
||||||
|
<y>1026</y>
|
||||||
|
<w>369</w>
|
||||||
|
<h>36</h>
|
||||||
|
</coordinates>
|
||||||
|
<panel_attributes>lt=->>
|
||||||
|
online
|
||||||
|
layer=0</panel_attributes>
|
||||||
|
<additional_attributes>390.0;20.0;10.0;20.0</additional_attributes>
|
||||||
|
</element>
|
||||||
|
</diagram>
|
@ -1,7 +1,7 @@
|
|||||||
package envoy.server.data;
|
package envoy.server.data;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
@ -121,9 +121,8 @@ public final class PersistenceManager {
|
|||||||
transaction(() -> {
|
transaction(() -> {
|
||||||
|
|
||||||
// Remove this contact from the contact list of his contacts
|
// Remove this contact from the contact list of his contacts
|
||||||
for (final var remainingContact : contact.contacts)
|
for (final var remainingContact : contact.getContacts())
|
||||||
remainingContact.getContacts().remove(contact);
|
remainingContact.getContacts().remove(contact);
|
||||||
contact.contacts.clear();
|
|
||||||
});
|
});
|
||||||
remove(contact);
|
remove(contact);
|
||||||
}
|
}
|
||||||
@ -224,9 +223,6 @@ public final class PersistenceManager {
|
|||||||
* @since Envoy Server Standalone v0.2-beta
|
* @since Envoy Server Standalone v0.2-beta
|
||||||
*/
|
*/
|
||||||
public List<Message> getPendingMessages(User user, Instant lastSync) {
|
public List<Message> getPendingMessages(User user, Instant lastSync) {
|
||||||
if (user == null)
|
|
||||||
return new ArrayList<>();
|
|
||||||
lastSync = Objects.requireNonNullElse(lastSync, Instant.EPOCH);
|
|
||||||
return entityManager.createNamedQuery(Message.getPending).setParameter("user", user)
|
return entityManager.createNamedQuery(Message.getPending).setParameter("user", user)
|
||||||
.setParameter("lastSeen", lastSync).getResultList();
|
.setParameter("lastSeen", lastSync).getResultList();
|
||||||
}
|
}
|
||||||
@ -240,9 +236,6 @@ public final class PersistenceManager {
|
|||||||
* @since Envoy Server Standalone v0.2-beta
|
* @since Envoy Server Standalone v0.2-beta
|
||||||
*/
|
*/
|
||||||
public List<GroupMessage> getPendingGroupMessages(User user, Instant lastSync) {
|
public List<GroupMessage> getPendingGroupMessages(User user, Instant lastSync) {
|
||||||
if (user == null)
|
|
||||||
return new ArrayList<>();
|
|
||||||
lastSync = Objects.requireNonNullElse(lastSync, Instant.EPOCH);
|
|
||||||
return entityManager.createNamedQuery(GroupMessage.getPendingGroupMsg)
|
return entityManager.createNamedQuery(GroupMessage.getPendingGroupMsg)
|
||||||
.setParameter("userId", user.getID())
|
.setParameter("userId", user.getID())
|
||||||
.setParameter("lastSeen", lastSync)
|
.setParameter("lastSeen", lastSync)
|
||||||
@ -284,18 +277,16 @@ public final class PersistenceManager {
|
|||||||
* @since Envoy Server v0.3-beta
|
* @since Envoy Server v0.3-beta
|
||||||
*/
|
*/
|
||||||
public void addContactBidirectional(Contact contact1, Contact contact2) {
|
public void addContactBidirectional(Contact contact1, Contact contact2) {
|
||||||
if (!(contact1 == null || contact2 == null)) {
|
|
||||||
|
|
||||||
// Add users to each others contact list
|
// Add users to each others contact list
|
||||||
contact1.getContacts().add(contact2);
|
contact1.getContacts().add(contact2);
|
||||||
contact2.getContacts().add(contact1);
|
contact2.getContacts().add(contact1);
|
||||||
|
|
||||||
// Synchronize changes with the database
|
// Synchronize changes with the database
|
||||||
transaction(() -> {
|
transaction(() -> {
|
||||||
entityManager.merge(contact1);
|
entityManager.merge(contact1);
|
||||||
entityManager.merge(contact2);
|
entityManager.merge(contact2);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -317,18 +308,16 @@ public final class PersistenceManager {
|
|||||||
* @since Envoy Server v0.3-beta
|
* @since Envoy Server v0.3-beta
|
||||||
*/
|
*/
|
||||||
public void removeContactBidirectional(Contact contact1, Contact contact2) {
|
public void removeContactBidirectional(Contact contact1, Contact contact2) {
|
||||||
if (!(contact1 == null || contact2 == null)) {
|
|
||||||
|
|
||||||
// Remove users from each others contact list
|
// Remove users from each others contact list
|
||||||
contact1.getContacts().remove(contact2);
|
contact1.getContacts().remove(contact2);
|
||||||
contact2.getContacts().remove(contact1);
|
contact2.getContacts().remove(contact1);
|
||||||
|
|
||||||
// Synchronize changes with the database
|
// Synchronize changes with the database
|
||||||
transaction(() -> {
|
transaction(() -> {
|
||||||
entityManager.merge(contact1);
|
entityManager.merge(contact1);
|
||||||
entityManager.merge(contact2);
|
entityManager.merge(contact2);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -342,36 +331,15 @@ public final class PersistenceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void persist(Object obj) {
|
private void persist(Object obj) {
|
||||||
try {
|
transaction(() -> entityManager.persist(obj));
|
||||||
transaction(() -> entityManager.persist(obj));
|
|
||||||
} catch (EntityExistsException e) {
|
|
||||||
if (transaction.isActive())
|
|
||||||
transaction.rollback();
|
|
||||||
EnvoyLog.getLogger(PersistenceManager.class).log(Level.WARNING,
|
|
||||||
String.format("Could not persist %s: entity exists already.", obj));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void merge(Object obj) {
|
private void merge(Object obj) {
|
||||||
try {
|
transaction(() -> entityManager.merge(obj));
|
||||||
transaction(() -> entityManager.merge(obj));
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
if (transaction.isActive())
|
|
||||||
transaction.rollback();
|
|
||||||
EnvoyLog.getLogger(PersistenceManager.class).log(Level.WARNING,
|
|
||||||
String.format("Could not merge %s: entity doesn't exist.", obj));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void remove(Object obj) {
|
private void remove(Object obj) {
|
||||||
try {
|
transaction(() -> entityManager.remove(obj));
|
||||||
transaction(() -> entityManager.remove(obj));
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
if (transaction.isActive())
|
|
||||||
transaction.rollback();
|
|
||||||
EnvoyLog.getLogger(PersistenceManager.class).log(Level.WARNING,
|
|
||||||
String.format("Could not remove %s: entity didn't exist (for the database).", obj));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,10 +49,8 @@ public final class ConnectionManager implements ISocketIdListener {
|
|||||||
// Notify contacts of this users offline-going
|
// Notify contacts of this users offline-going
|
||||||
final envoy.server.data.User user =
|
final envoy.server.data.User user =
|
||||||
PersistenceManager.getInstance().getUserByID(getUserIDBySocketID(socketID));
|
PersistenceManager.getInstance().getUserByID(getUserIDBySocketID(socketID));
|
||||||
if (user != null) {
|
user.setLastSeen(Instant.now());
|
||||||
user.setLastSeen(Instant.now());
|
UserStatusChangeProcessor.updateUserStatus(user, UserStatus.OFFLINE);
|
||||||
UserStatusChangeProcessor.updateUserStatus(user, UserStatus.OFFLINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the socket
|
// Remove the socket
|
||||||
sockets.entrySet().removeIf(e -> e.getValue() == socketID);
|
sockets.entrySet().removeIf(e -> e.getValue() == socketID);
|
||||||
|
@ -33,6 +33,7 @@ public final class ObjectMessageProcessor implements IMessageProcessor {
|
|||||||
this.processors = processors;
|
this.processors = processors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void process(Message message, WriteProxy writeProxy) {
|
public void process(Message message, WriteProxy writeProxy) {
|
||||||
try (ObjectInputStream in =
|
try (ObjectInputStream in =
|
||||||
@ -44,34 +45,23 @@ public final class ObjectMessageProcessor implements IMessageProcessor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log(Level.INFO, "Received " + obj);
|
logger.fine("Received " + obj);
|
||||||
|
|
||||||
refer(message.socketId, writeProxy, obj);
|
// Get processor and input class and process object
|
||||||
|
for (@SuppressWarnings("rawtypes")
|
||||||
|
ObjectProcessor p : processors) {
|
||||||
|
Class<?> c = (Class<?>) ((ParameterizedType) p.getClass().getGenericInterfaces()[0])
|
||||||
|
.getActualTypeArguments()[0];
|
||||||
|
if (c.equals(obj.getClass()))
|
||||||
|
try {
|
||||||
|
p.process(c.cast(obj), message.socketId, new ObjectWriteProxy(writeProxy));
|
||||||
|
break;
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.log(Level.SEVERE, "Exception during processor execution: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (IOException | ClassNotFoundException e) {
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
logger.log(Level.WARNING,
|
e.printStackTrace();
|
||||||
"An exception occurred when reading in an object: " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the appropriate {@link ObjectProcessor} for the given input ({@code obj}), if any is
|
|
||||||
* present.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void refer(long socketID, WriteProxy writeProxy, Object obj) {
|
|
||||||
|
|
||||||
// Get processor and input class and process object
|
|
||||||
for (@SuppressWarnings("rawtypes")
|
|
||||||
ObjectProcessor p : processors) {
|
|
||||||
Class<?> c = (Class<?>) ((ParameterizedType) p.getClass().getGenericInterfaces()[0])
|
|
||||||
.getActualTypeArguments()[0];
|
|
||||||
if (c.equals(obj.getClass()))
|
|
||||||
try {
|
|
||||||
p.process(c.cast(obj), socketID, new ObjectWriteProxy(writeProxy));
|
|
||||||
break;
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.log(Level.SEVERE, "Exception during processor execution: ", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import static envoy.server.Startup.config;
|
|||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.logging.*;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.persistence.EntityExistsException;
|
import javax.persistence.EntityExistsException;
|
||||||
|
|
||||||
@ -15,7 +15,6 @@ import envoy.util.EnvoyLog;
|
|||||||
|
|
||||||
import envoy.server.data.PersistenceManager;
|
import envoy.server.data.PersistenceManager;
|
||||||
import envoy.server.net.*;
|
import envoy.server.net.*;
|
||||||
import envoy.server.util.UserAuthenticationUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Maximilian Käfer
|
* @author Maximilian Käfer
|
||||||
@ -30,15 +29,6 @@ public final class GroupMessageProcessor implements ObjectProcessor<GroupMessage
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(GroupMessage groupMessage, long socketID, ObjectWriteProxy writeProxy) {
|
public void process(GroupMessage groupMessage, long socketID, ObjectWriteProxy writeProxy) {
|
||||||
|
|
||||||
// Check whether the message has the expected parameters
|
|
||||||
if (!UserAuthenticationUtil.isExpectedUser(groupMessage.getSenderID(), socketID)
|
|
||||||
|| persistenceManager.getContactByID(groupMessage.getRecipientID()) == null) {
|
|
||||||
logger.log(Level.INFO,
|
|
||||||
"Received a group message with invalid parameters");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
groupMessage.nextStatus();
|
groupMessage.nextStatus();
|
||||||
|
|
||||||
// Update statuses to SENT / RECEIVED depending on online status
|
// Update statuses to SENT / RECEIVED depending on online status
|
||||||
|
@ -12,7 +12,6 @@ import envoy.util.EnvoyLog;
|
|||||||
|
|
||||||
import envoy.server.data.*;
|
import envoy.server.data.*;
|
||||||
import envoy.server.net.*;
|
import envoy.server.net.*;
|
||||||
import envoy.server.util.UserAuthenticationUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Maximilian Käfer
|
* @author Maximilian Käfer
|
||||||
@ -29,17 +28,7 @@ public final class GroupMessageStatusChangeProcessor
|
|||||||
@Override
|
@Override
|
||||||
public void process(GroupMessageStatusChange statusChange, long socketID,
|
public void process(GroupMessageStatusChange statusChange, long socketID,
|
||||||
ObjectWriteProxy writeProxy) {
|
ObjectWriteProxy writeProxy) {
|
||||||
|
|
||||||
// Check whether the message has the expected parameters
|
|
||||||
if (!UserAuthenticationUtil.isExpectedUser(statusChange.getMemberID(), socketID)) {
|
|
||||||
logger.log(Level.INFO,
|
|
||||||
"Received a group message with invalid parameters");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GroupMessage gmsg = (GroupMessage) persistenceManager.getMessageByID(statusChange.getID());
|
GroupMessage gmsg = (GroupMessage) persistenceManager.getMessageByID(statusChange.getID());
|
||||||
if (gmsg == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Any other status than READ is not supposed to be sent to the server
|
// Any other status than READ is not supposed to be sent to the server
|
||||||
if (statusChange.get() != MessageStatus.READ) {
|
if (statusChange.get() != MessageStatus.READ) {
|
||||||
|
@ -24,10 +24,6 @@ public final class GroupResizeProcessor implements ObjectProcessor<GroupResize>
|
|||||||
final var group = persistenceManager.getGroupByID(groupResize.getGroupID());
|
final var group = persistenceManager.getGroupByID(groupResize.getGroupID());
|
||||||
final var sender = persistenceManager.getUserByID(groupResize.get().getID());
|
final var sender = persistenceManager.getUserByID(groupResize.get().getID());
|
||||||
|
|
||||||
// TODO: Inform the sender that this group has already been deleted
|
|
||||||
if (group == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Perform the desired operation
|
// Perform the desired operation
|
||||||
switch (groupResize.getOperation()) {
|
switch (groupResize.getOperation()) {
|
||||||
case ADD:
|
case ADD:
|
||||||
|
@ -23,11 +23,10 @@ public final class IsTypingProcessor implements ObjectProcessor<IsTyping> {
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
final var contact = persistenceManager.getContactByID(event.get());
|
final var contact = persistenceManager.getContactByID(event.get());
|
||||||
if (contact instanceof User) {
|
if (contact instanceof User) {
|
||||||
if (connectionManager.isOnline(event.get()))
|
final var destinationID = event.getDestinationID();
|
||||||
writeProxy.write(connectionManager.getSocketID(event.get()),
|
if (connectionManager.isOnline(destinationID))
|
||||||
new IsTyping(connectionManager.getUserIDBySocketID(socketID)));
|
writeProxy.write(connectionManager.getSocketID(destinationID), event);
|
||||||
} else
|
} else
|
||||||
writeProxy.writeToOnlineContacts(contact.getContacts(),
|
writeProxy.writeToOnlineContacts(contact.getContacts(), event);
|
||||||
new IsTyping(connectionManager.getUserIDBySocketID(socketID)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,7 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
|
|||||||
// Process token request
|
// Process token request
|
||||||
if (credentials.requestToken()) {
|
if (credentials.requestToken()) {
|
||||||
String token;
|
String token;
|
||||||
|
|
||||||
if (user.getAuthToken() != null && user.getAuthTokenExpiration().isAfter(Instant.now()))
|
if (user.getAuthToken() != null && user.getAuthTokenExpiration().isAfter(Instant.now()))
|
||||||
|
|
||||||
// Reuse existing token and delay expiration date
|
// Reuse existing token and delay expiration date
|
||||||
@ -138,6 +139,7 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
|
|||||||
persistenceManager.updateContact(user);
|
persistenceManager.updateContact(user);
|
||||||
writeProxy.write(socketID, new NewAuthToken(token));
|
writeProxy.write(socketID, new NewAuthToken(token));
|
||||||
}
|
}
|
||||||
|
|
||||||
final var pendingMessages =
|
final var pendingMessages =
|
||||||
PersistenceManager.getInstance().getPendingMessages(user, credentials.getLastSync());
|
PersistenceManager.getInstance().getPendingMessages(user, credentials.getLastSync());
|
||||||
pendingMessages.removeIf(GroupMessage.class::isInstance);
|
pendingMessages.removeIf(GroupMessage.class::isInstance);
|
||||||
|
@ -12,7 +12,6 @@ import envoy.util.EnvoyLog;
|
|||||||
|
|
||||||
import envoy.server.data.PersistenceManager;
|
import envoy.server.data.PersistenceManager;
|
||||||
import envoy.server.net.*;
|
import envoy.server.net.*;
|
||||||
import envoy.server.util.UserAuthenticationUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This {@link ObjectProcessor} handles incoming {@link Message}s.
|
* This {@link ObjectProcessor} handles incoming {@link Message}s.
|
||||||
@ -30,15 +29,6 @@ public final class MessageProcessor implements ObjectProcessor<Message> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(Message message, long socketID, ObjectWriteProxy writeProxy) {
|
public void process(Message message, long socketID, ObjectWriteProxy writeProxy) {
|
||||||
|
|
||||||
// Check whether the message has the expected parameters
|
|
||||||
if (!UserAuthenticationUtil.isExpectedUser(message.getSenderID(), socketID)
|
|
||||||
|| persistenceManager.getContactByID(message.getRecipientID()) == null) {
|
|
||||||
logger.log(Level.INFO,
|
|
||||||
"Received a message with invalid parameters");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
message.nextStatus();
|
message.nextStatus();
|
||||||
|
|
||||||
// Convert to server message
|
// Convert to server message
|
||||||
|
@ -32,8 +32,6 @@ public final class MessageStatusChangeProcessor implements ObjectProcessor<Messa
|
|||||||
}
|
}
|
||||||
|
|
||||||
final var msg = persistenceManager.getMessageByID(statusChange.getID());
|
final var msg = persistenceManager.getMessageByID(statusChange.getID());
|
||||||
if (msg == null)
|
|
||||||
return;
|
|
||||||
msg.read();
|
msg.read();
|
||||||
persistenceManager.updateMessage(msg);
|
persistenceManager.updateMessage(msg);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import envoy.event.*;
|
|||||||
import envoy.util.EnvoyLog;
|
import envoy.util.EnvoyLog;
|
||||||
|
|
||||||
import envoy.server.data.PersistenceManager;
|
import envoy.server.data.PersistenceManager;
|
||||||
import envoy.server.net.*;
|
import envoy.server.net.ObjectWriteProxy;
|
||||||
import envoy.server.util.PasswordUtil;
|
import envoy.server.util.PasswordUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,8 +21,7 @@ public final class PasswordChangeRequestProcessor
|
|||||||
public void process(PasswordChangeRequest event, long socketID, ObjectWriteProxy writeProxy)
|
public void process(PasswordChangeRequest event, long socketID, ObjectWriteProxy writeProxy)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final var persistenceManager = PersistenceManager.getInstance();
|
final var persistenceManager = PersistenceManager.getInstance();
|
||||||
final var user = persistenceManager
|
final var user = persistenceManager.getUserByID(event.getID());
|
||||||
.getUserByID(ConnectionManager.getInstance().getUserIDBySocketID(socketID));
|
|
||||||
final var logger =
|
final var logger =
|
||||||
EnvoyLog.getLogger(PasswordChangeRequestProcessor.class);
|
EnvoyLog.getLogger(PasswordChangeRequestProcessor.class);
|
||||||
final var correctAuthentication =
|
final var correctAuthentication =
|
||||||
|
@ -22,16 +22,10 @@ public final class UserOperationProcessor implements ObjectProcessor<UserOperati
|
|||||||
private static final PersistenceManager persistenceManager = PersistenceManager.getInstance();
|
private static final PersistenceManager persistenceManager = PersistenceManager.getInstance();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(UserOperation evt, long socketID, ObjectWriteProxy writeProxy) {
|
public void process(UserOperation evt, long socketId, ObjectWriteProxy writeProxy) {
|
||||||
final long userID = ConnectionManager.getInstance().getUserIDBySocketID(socketID);
|
final long userID = ConnectionManager.getInstance().getUserIDBySocketID(socketId);
|
||||||
final long contactID = evt.get().getID();
|
final long contactID = evt.get().getID();
|
||||||
final var recipient = persistenceManager.getUserByID(contactID);
|
final var sender = persistenceManager.getUserByID(userID);
|
||||||
|
|
||||||
// TODO: Inform the sender if the requested contact has already been deleted
|
|
||||||
if (recipient == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
final var sender = persistenceManager.getUserByID(userID);
|
|
||||||
switch (evt.getOperationType()) {
|
switch (evt.getOperationType()) {
|
||||||
case ADD:
|
case ADD:
|
||||||
logger.log(Level.FINE,
|
logger.log(Level.FINE,
|
||||||
@ -51,7 +45,7 @@ public final class UserOperationProcessor implements ObjectProcessor<UserOperati
|
|||||||
sender.setLatestContactDeletion(Instant.now());
|
sender.setLatestContactDeletion(Instant.now());
|
||||||
|
|
||||||
// Notify the removed contact on next startup(s) of this deletion
|
// Notify the removed contact on next startup(s) of this deletion
|
||||||
recipient.setLatestContactDeletion(Instant.now());
|
persistenceManager.getUserByID(contactID).setLatestContactDeletion(Instant.now());
|
||||||
|
|
||||||
// Notify the removed contact if online
|
// Notify the removed contact if online
|
||||||
if (connectionManager.isOnline(contactID))
|
if (connectionManager.isOnline(contactID))
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
package envoy.server.util;
|
|
||||||
|
|
||||||
import envoy.server.net.ConnectionManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Leon Hofmeister
|
|
||||||
* @since Envoy Server v0.3-beta
|
|
||||||
*/
|
|
||||||
public final class UserAuthenticationUtil {
|
|
||||||
|
|
||||||
private UserAuthenticationUtil() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether a user is really who he claims to be.
|
|
||||||
*
|
|
||||||
* @param expectedID the expected user ID
|
|
||||||
* @param socketID the socket ID of the user making a request
|
|
||||||
* @return whether this user is who he claims to be
|
|
||||||
* @since Envoy Server v0.3-beta
|
|
||||||
*/
|
|
||||||
public static boolean isExpectedUser(long expectedID, long socketID) {
|
|
||||||
return ConnectionManager.getInstance().getUserIDBySocketID(socketID) == expectedID;
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user