Merge branch 'develop' into b/ui-fixes
All checks were successful
zdm/envoy/pipeline/head This commit looks good
All checks were successful
zdm/envoy/pipeline/head This commit looks good
This commit is contained in:
commit
05ed5da41b
37
Jenkinsfile
vendored
Normal file
37
Jenkinsfile
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
options {
|
||||
ansiColor('xterm')
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh 'mvn -DskipTests clean package'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh 'mvn test'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
junit '*/target/surefire-reports/*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('SonarQube Analysis') {
|
||||
steps {
|
||||
withSonarQubeEnv('KSKE SonarQube') {
|
||||
sh 'mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.9.1.2184:sonar'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
archiveArtifacts artifacts: 'client/target/envoy-client-*-shaded.jar, server/target/envoy-server-jar-with-dependencies.jar'
|
||||
}
|
||||
}
|
||||
}
|
@ -17,6 +17,8 @@ If you want to transfer a file to another user, you can attach it to a message.
|
||||
|
||||
On the settings page some convenience features can be configured, as well as the color theme.
|
||||
|
||||
Additional info on how to use Envoy can be found [here](https://git.kske.dev/zdm/envoy/wiki) in the client section.
|
||||
|
||||
### System requirements
|
||||
|
||||
To run Envoy, you have to install a Java Runtime Environment (JRE) of at least version 11.
|
||||
@ -29,7 +31,7 @@ Most major Linux distributions like Debian, Arch and Gentoo have a Noto emoji pa
|
||||
|
||||
To set up an Envoy server, download the package from the release page.
|
||||
|
||||
Because the project lacks external documentation for the moment, please refer to the Javadoc inside the source code to configure your Envoy instance.
|
||||
To configure the behavior of Envoy Server, please have a look at the [documentation](https://git.kske.dev/zdm/envoy/wiki), specifically the server part.
|
||||
|
||||
### System requirements
|
||||
|
||||
|
@ -13,9 +13,8 @@ import java.util.stream.Stream;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.*;
|
||||
|
||||
import dev.kske.eventbus.Event;
|
||||
import dev.kske.eventbus.EventBus;
|
||||
import dev.kske.eventbus.EventListener;
|
||||
import dev.kske.eventbus.core.*;
|
||||
import dev.kske.eventbus.core.Event;
|
||||
|
||||
import envoy.data.*;
|
||||
import envoy.data.Message.MessageStatus;
|
||||
@ -35,7 +34,7 @@ import envoy.client.event.*;
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Client v0.3-alpha
|
||||
*/
|
||||
public final class LocalDB implements EventListener {
|
||||
public final class LocalDB {
|
||||
|
||||
// Data
|
||||
private User user;
|
||||
@ -246,7 +245,8 @@ public final class LocalDB implements EventListener {
|
||||
* @throws IOException if the saving process failed
|
||||
* @since Envoy Client v0.3-alpha
|
||||
*/
|
||||
@Event(eventType = EnvoyCloseEvent.class, priority = 500)
|
||||
@Event(EnvoyCloseEvent.class)
|
||||
@Priority(500)
|
||||
private synchronized void save() {
|
||||
|
||||
// Stop saving if this account has been deleted
|
||||
@ -300,37 +300,43 @@ public final class LocalDB implements EventListener {
|
||||
onLogout();
|
||||
}
|
||||
|
||||
@Event(priority = 500)
|
||||
@Event
|
||||
@Priority(500)
|
||||
private void onMessage(Message msg) {
|
||||
if (msg.getStatus() == MessageStatus.SENT)
|
||||
msg.nextStatus();
|
||||
}
|
||||
|
||||
@Event(priority = 500)
|
||||
@Event
|
||||
@Priority(500)
|
||||
private void onGroupMessage(GroupMessage msg) {
|
||||
// TODO: Cancel event once EventBus is updated
|
||||
if (msg.getStatus() == MessageStatus.WAITING || msg.getStatus() == MessageStatus.READ)
|
||||
logger.warning("The groupMessage has the unexpected status " + msg.getStatus());
|
||||
}
|
||||
|
||||
@Event(priority = 500)
|
||||
@Event
|
||||
@Priority(500)
|
||||
private void onMessageStatusChange(MessageStatusChange evt) {
|
||||
getMessage(evt.getID()).ifPresent(msg -> msg.setStatus(evt.get()));
|
||||
}
|
||||
|
||||
@Event(priority = 500)
|
||||
@Event
|
||||
@Priority(500)
|
||||
private void onGroupMessageStatusChange(GroupMessageStatusChange evt) {
|
||||
this.<GroupMessage>getMessage(evt.getID())
|
||||
.ifPresent(msg -> msg.getMemberStatuses().replace(evt.getMemberID(), evt.get()));
|
||||
}
|
||||
|
||||
@Event(priority = 500)
|
||||
@Event
|
||||
@Priority(500)
|
||||
private void onUserStatusChange(UserStatusChange evt) {
|
||||
getChat(evt.getID()).map(Chat::getRecipient).map(User.class::cast)
|
||||
.ifPresent(u -> u.setStatus(evt.get()));
|
||||
}
|
||||
|
||||
@Event(priority = 500)
|
||||
@Event
|
||||
@Priority(500)
|
||||
private void onUserOperation(UserOperation operation) {
|
||||
final var eventUser = operation.get();
|
||||
switch (operation.getOperationType()) {
|
||||
@ -356,13 +362,15 @@ public final class LocalDB implements EventListener {
|
||||
Platform.runLater(() -> chats.add(new GroupChat(user, newGroup)));
|
||||
}
|
||||
|
||||
@Event(priority = 500)
|
||||
@Event
|
||||
@Priority(500)
|
||||
private void onGroupResize(GroupResize evt) {
|
||||
getChat(evt.getGroupID()).map(Chat::getRecipient).map(Group.class::cast)
|
||||
.ifPresent(evt::apply);
|
||||
}
|
||||
|
||||
@Event(priority = 500)
|
||||
@Event
|
||||
@Priority(500)
|
||||
private void onNameChange(NameChange evt) {
|
||||
chats.stream().map(Chat::getRecipient).filter(c -> c.getID() == evt.getID()).findAny()
|
||||
.ifPresent(c -> c.setName(evt.get()));
|
||||
@ -384,7 +392,8 @@ public final class LocalDB implements EventListener {
|
||||
*
|
||||
* @since Envoy Client v0.2-beta
|
||||
*/
|
||||
@Event(eventType = Logout.class, priority = 50)
|
||||
@Event(Logout.class)
|
||||
@Priority(50)
|
||||
private void onLogout() {
|
||||
autoSaver.cancel();
|
||||
autoSaveRestart = true;
|
||||
@ -416,22 +425,26 @@ public final class LocalDB implements EventListener {
|
||||
});
|
||||
}
|
||||
|
||||
@Event(priority = 500)
|
||||
@Event
|
||||
@Priority(500)
|
||||
private void onOwnStatusChange(OwnStatusChange statusChange) {
|
||||
user.setStatus(statusChange.get());
|
||||
}
|
||||
|
||||
@Event(eventType = ContactsChangedSinceLastLogin.class, priority = 500)
|
||||
@Event(ContactsChangedSinceLastLogin.class)
|
||||
@Priority(500)
|
||||
private void onContactsChangedSinceLastLogin() {
|
||||
contactsChanged = true;
|
||||
}
|
||||
|
||||
@Event(priority = 500)
|
||||
@Event
|
||||
@Priority(500)
|
||||
private void onContactDisabled(ContactDisabled event) {
|
||||
getChat(event.get().getID()).ifPresent(chat -> chat.setDisabled(true));
|
||||
}
|
||||
|
||||
@Event(priority = 500)
|
||||
@Event
|
||||
@Priority(500)
|
||||
private void onAccountDeletion(AccountDeletion deletion) {
|
||||
if (user.getID() == deletion.get())
|
||||
logger.log(Level.WARNING,
|
||||
@ -496,7 +509,8 @@ public final class LocalDB implements EventListener {
|
||||
* @param idGenerator the message ID generator to set
|
||||
* @since Envoy Client v0.3-alpha
|
||||
*/
|
||||
@Event(priority = 150)
|
||||
@Event
|
||||
@Priority(150)
|
||||
public void setIDGenerator(IDGenerator idGenerator) { this.idGenerator = idGenerator; }
|
||||
|
||||
/**
|
||||
|
@ -5,8 +5,7 @@ import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
import dev.kske.eventbus.EventListener;
|
||||
import dev.kske.eventbus.core.*;
|
||||
|
||||
import envoy.util.*;
|
||||
|
||||
@ -21,7 +20,7 @@ import envoy.client.event.EnvoyCloseEvent;
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Client v0.2-alpha
|
||||
*/
|
||||
public final class Settings implements EventListener {
|
||||
public final class Settings {
|
||||
|
||||
// Actual settings accessible by the rest of the application
|
||||
private Map<String, SettingsItem<?>> items;
|
||||
@ -69,7 +68,7 @@ public final class Settings implements EventListener {
|
||||
* @throws IOException if an error occurs while saving the themes
|
||||
* @since Envoy Client v0.2-alpha
|
||||
*/
|
||||
@Event(eventType = EnvoyCloseEvent.class)
|
||||
@Event(EnvoyCloseEvent.class)
|
||||
private void save() {
|
||||
EnvoyLog.getLogger(Settings.class).log(Level.INFO, "Saving settings...");
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
package envoy.client.helper;
|
||||
|
||||
import dev.kske.eventbus.EventBus;
|
||||
import dev.kske.eventbus.core.EventBus;
|
||||
|
||||
import envoy.client.data.*;
|
||||
import envoy.client.event.EnvoyCloseEvent;
|
||||
|
@ -5,14 +5,14 @@ import java.net.Socket;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.*;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
import dev.kske.eventbus.Event;
|
||||
import dev.kske.eventbus.core.*;
|
||||
import dev.kske.eventbus.core.Event;
|
||||
|
||||
import envoy.data.*;
|
||||
import envoy.event.*;
|
||||
import envoy.util.*;
|
||||
|
||||
import envoy.client.data.*;
|
||||
import envoy.client.data.ClientConfig;
|
||||
import envoy.client.event.EnvoyCloseEvent;
|
||||
|
||||
/**
|
||||
@ -24,7 +24,7 @@ import envoy.client.event.EnvoyCloseEvent;
|
||||
* @author Leon Hofmeister
|
||||
* @since Envoy Client v0.1-alpha
|
||||
*/
|
||||
public final class Client implements EventListener, Closeable {
|
||||
public final class Client implements Closeable {
|
||||
|
||||
// Connection handling
|
||||
private Socket socket;
|
||||
@ -55,13 +55,12 @@ public final class Client implements EventListener, Closeable {
|
||||
* the handshake does exceed this time limit, an exception is thrown.
|
||||
*
|
||||
* @param credentials the login credentials of the user
|
||||
* @param cacheMap the map of all caches needed
|
||||
* @throws TimeoutException if the server could not be reached
|
||||
* @throws IOException if the login credentials could not be written
|
||||
* @throws InterruptedException if the current thread is interrupted while waiting for the
|
||||
* handshake response
|
||||
*/
|
||||
public void performHandshake(LoginCredentials credentials, CacheMap cacheMap)
|
||||
public void performHandshake(LoginCredentials credentials)
|
||||
throws TimeoutException, IOException, InterruptedException {
|
||||
if (online)
|
||||
throw new IllegalStateException("Handshake has already been performed successfully");
|
||||
@ -79,7 +78,6 @@ public final class Client implements EventListener, Closeable {
|
||||
// Register user creation processor, contact list processor, message cache and
|
||||
// authentication token
|
||||
receiver.registerProcessor(User.class, sender -> this.sender = sender);
|
||||
receiver.registerProcessors(cacheMap.getMap());
|
||||
|
||||
// Start receiver
|
||||
receiver.start();
|
||||
@ -101,42 +99,18 @@ public final class Client implements EventListener, Closeable {
|
||||
|
||||
if (System.currentTimeMillis() - start > 5000) {
|
||||
rejected = true;
|
||||
socket.close();
|
||||
receiver.removeAllProcessors();
|
||||
throw new TimeoutException("Did not log in after 5 seconds");
|
||||
}
|
||||
Thread.sleep(500);
|
||||
}
|
||||
|
||||
online = true;
|
||||
logger.log(Level.INFO, "Handshake completed.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the {@link Receiver} used to process data sent from the server to this client.
|
||||
*
|
||||
* @param localDB the local database used to persist the current {@link IDGenerator}
|
||||
* @param cacheMap the map of all caches needed
|
||||
* @throws IOException if no {@link IDGenerator} is present and none could be requested from the
|
||||
* server
|
||||
* @since Envoy Client v0.2-alpha
|
||||
*/
|
||||
public void initReceiver(LocalDB localDB, CacheMap cacheMap) throws IOException {
|
||||
checkOnline();
|
||||
|
||||
// Remove all processors as they are only used during the handshake
|
||||
// Remove handshake specific processors
|
||||
receiver.removeAllProcessors();
|
||||
|
||||
// Relay cached messages and message status changes
|
||||
cacheMap.get(Message.class).setProcessor(eventBus::dispatch);
|
||||
cacheMap.get(GroupMessage.class).setProcessor(eventBus::dispatch);
|
||||
cacheMap.get(MessageStatusChange.class).setProcessor(eventBus::dispatch);
|
||||
cacheMap.get(GroupMessageStatusChange.class).setProcessor(eventBus::dispatch);
|
||||
|
||||
// Request a generator if none is present or the existing one is consumed
|
||||
if (!localDB.hasIDGenerator() || !localDB.getIDGenerator().hasNext())
|
||||
requestIDGenerator();
|
||||
|
||||
// Relay caches
|
||||
cacheMap.getMap().values().forEach(Cache::relay);
|
||||
online = true;
|
||||
logger.log(Level.INFO, "Handshake completed.");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -179,13 +153,15 @@ public final class Client implements EventListener, Closeable {
|
||||
send(new IDGeneratorRequest());
|
||||
}
|
||||
|
||||
@Event(eventType = HandshakeRejection.class, priority = 1000)
|
||||
@Event(HandshakeRejection.class)
|
||||
@Priority(1000)
|
||||
private void onHandshakeRejection() {
|
||||
rejected = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Event(eventType = EnvoyCloseEvent.class, priority = 50)
|
||||
@Event(EnvoyCloseEvent.class)
|
||||
@Priority(50)
|
||||
public void close() {
|
||||
if (online) {
|
||||
logger.log(Level.INFO, "Closing connection...");
|
||||
|
@ -6,7 +6,7 @@ import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.*;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
import dev.kske.eventbus.core.EventBus;
|
||||
|
||||
import envoy.util.*;
|
||||
|
||||
@ -87,15 +87,17 @@ public final class Receiver extends Thread {
|
||||
// Dispatch to the processor if present
|
||||
if (processor != null)
|
||||
processor.accept(obj);
|
||||
// Dispatch to the event bus if the object is an event without a processor
|
||||
else if (obj instanceof IEvent)
|
||||
eventBus.dispatch((IEvent) obj);
|
||||
// Notify if no processor could be located
|
||||
// Dispatch to the event bus if the object has no processor
|
||||
else
|
||||
logger.log(Level.WARNING,
|
||||
String.format(
|
||||
"The received object has the %s for which no processor is defined.",
|
||||
obj.getClass()));
|
||||
eventBus.dispatch(obj);
|
||||
|
||||
// TODO: Log DeadEvent from Event Bus 1.1.0
|
||||
// Notify if no processor could be located
|
||||
// else
|
||||
// logger.log(Level.WARNING,
|
||||
// String.format(
|
||||
// "The received object has the %s for which no processor is defined.",
|
||||
// obj.getClass()));
|
||||
}
|
||||
} catch (final SocketException | EOFException e) {
|
||||
// Connection probably closed by client.
|
||||
|
@ -8,7 +8,7 @@ import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.*;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
import dev.kske.eventbus.core.*;
|
||||
|
||||
import envoy.util.EnvoyLog;
|
||||
|
||||
@ -25,7 +25,7 @@ import envoy.client.event.*;
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public final class SceneContext implements EventListener {
|
||||
public final class SceneContext {
|
||||
|
||||
private final Stage stage;
|
||||
private final Stack<Parent> roots = new Stack<>();
|
||||
@ -126,13 +126,15 @@ public final class SceneContext implements EventListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Event(eventType = Logout.class, priority = 150)
|
||||
@Event(Logout.class)
|
||||
@Priority(150)
|
||||
private void onLogout() {
|
||||
roots.clear();
|
||||
controllers.clear();
|
||||
}
|
||||
|
||||
@Event(priority = 150, eventType = ThemeChangeEvent.class)
|
||||
@Event(ThemeChangeEvent.class)
|
||||
@Priority(150)
|
||||
private void onThemeChange() {
|
||||
applyCSS();
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import javafx.stage.Stage;
|
||||
|
||||
import envoy.data.*;
|
||||
import envoy.data.User.UserStatus;
|
||||
import envoy.event.*;
|
||||
import envoy.event.UserStatusChange;
|
||||
import envoy.exception.EnvoyException;
|
||||
import envoy.util.EnvoyLog;
|
||||
|
||||
@ -115,21 +115,20 @@ public final class Startup extends Application {
|
||||
* @since Envoy Client v0.2-beta
|
||||
*/
|
||||
public static boolean performHandshake(LoginCredentials credentials) {
|
||||
final var cacheMap = new CacheMap();
|
||||
cacheMap.put(Message.class, new Cache<Message>());
|
||||
cacheMap.put(GroupMessage.class, new Cache<GroupMessage>());
|
||||
cacheMap.put(MessageStatusChange.class, new Cache<MessageStatusChange>());
|
||||
cacheMap.put(GroupMessageStatusChange.class, new Cache<GroupMessageStatusChange>());
|
||||
final var originalStatus =
|
||||
localDB.getUser() == null ? UserStatus.ONLINE : localDB.getUser().getStatus();
|
||||
try {
|
||||
client.performHandshake(credentials, cacheMap);
|
||||
client.performHandshake(credentials);
|
||||
if (client.isOnline()) {
|
||||
|
||||
// Restore the original status as the server automatically returns status ONLINE
|
||||
client.getSender().setStatus(originalStatus);
|
||||
loadChatScene();
|
||||
client.initReceiver(localDB, cacheMap);
|
||||
|
||||
// Request an ID generator if none is present or the existing one is consumed
|
||||
if (!localDB.hasIDGenerator() || !localDB.getIDGenerator().hasNext())
|
||||
client.requestIDGenerator();
|
||||
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
@ -9,8 +9,8 @@ import java.awt.image.BufferedImage;
|
||||
import javafx.application.Platform;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
import dev.kske.eventbus.Event;
|
||||
import dev.kske.eventbus.core.Event;
|
||||
import dev.kske.eventbus.core.EventBus;
|
||||
|
||||
import envoy.data.Message;
|
||||
import envoy.data.User.UserStatus;
|
||||
@ -31,7 +31,7 @@ import envoy.client.util.*;
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Client v0.2-alpha
|
||||
*/
|
||||
public final class StatusTrayIcon implements EventListener {
|
||||
public final class StatusTrayIcon {
|
||||
|
||||
/**
|
||||
* The {@link TrayIcon} provided by the System Tray API for controlling the system tray. This
|
||||
@ -136,7 +136,7 @@ public final class StatusTrayIcon implements EventListener {
|
||||
*
|
||||
* @since Envoy Client v0.2-beta
|
||||
*/
|
||||
@Event(eventType = Logout.class)
|
||||
@Event(Logout.class)
|
||||
public void hide() {
|
||||
SystemTray.getSystemTray().remove(trayIcon);
|
||||
}
|
||||
|
@ -21,14 +21,14 @@ import javafx.scene.control.*;
|
||||
import javafx.scene.control.Alert.AlertType;
|
||||
import javafx.scene.image.*;
|
||||
import javafx.scene.input.*;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
import dev.kske.eventbus.Event;
|
||||
import dev.kske.eventbus.core.*;
|
||||
import dev.kske.eventbus.core.Event;
|
||||
|
||||
import envoy.data.*;
|
||||
import envoy.data.Attachment.AttachmentType;
|
||||
@ -55,7 +55,7 @@ import envoy.client.util.*;
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public final class ChatScene implements EventListener, Restorable, KeyboardMapping {
|
||||
public final class ChatScene implements Restorable, KeyboardMapping {
|
||||
|
||||
@FXML
|
||||
private ListView<Message> messageList;
|
||||
@ -220,12 +220,13 @@ public final class ChatScene implements EventListener, Restorable, KeyboardMappi
|
||||
});
|
||||
}
|
||||
|
||||
@Event(eventType = BackEvent.class)
|
||||
@Event(BackEvent.class)
|
||||
private void onBackEvent() {
|
||||
tabPane.getSelectionModel().select(Tabs.CONTACT_LIST.ordinal());
|
||||
}
|
||||
|
||||
@Event(includeSubtypes = true)
|
||||
@Event
|
||||
@Polymorphic
|
||||
private void onMessage(Message message) {
|
||||
|
||||
// The sender of the message is the recipient of the chat
|
||||
@ -304,7 +305,7 @@ public final class ChatScene implements EventListener, Restorable, KeyboardMappi
|
||||
}));
|
||||
}
|
||||
|
||||
@Event(eventType = NoAttachments.class)
|
||||
@Event(NoAttachments.class)
|
||||
private void onNoAttachments() {
|
||||
Platform.runLater(() -> {
|
||||
attachmentButton.setDisable(true);
|
||||
@ -317,12 +318,13 @@ public final class ChatScene implements EventListener, Restorable, KeyboardMappi
|
||||
});
|
||||
}
|
||||
|
||||
@Event(priority = 150)
|
||||
@Event
|
||||
@Priority(150)
|
||||
private void onGroupCreationResult(GroupCreationResult result) {
|
||||
Platform.runLater(() -> newGroupButton.setDisable(result.get() == null));
|
||||
}
|
||||
|
||||
@Event(eventType = ThemeChangeEvent.class)
|
||||
@Event(ThemeChangeEvent.class)
|
||||
private void onThemeChange() {
|
||||
ChatControl.reloadDefaultChatIcons();
|
||||
settingsButton.setGraphic(
|
||||
@ -346,12 +348,13 @@ public final class ChatScene implements EventListener, Restorable, KeyboardMappi
|
||||
recipientProfilePic.setImage(IconUtil.loadIconThemeSensitive("group_icon", 43));
|
||||
}
|
||||
|
||||
@Event(eventType = Logout.class, priority = 200)
|
||||
@Event(Logout.class)
|
||||
@Priority(200)
|
||||
private void onLogout() {
|
||||
eventBus.removeListener(this);
|
||||
}
|
||||
|
||||
@Event(eventType = AccountDeletion.class)
|
||||
@Event(AccountDeletion.class)
|
||||
private void onAccountDeletion() {
|
||||
Platform.runLater(chatList::refresh);
|
||||
}
|
||||
@ -783,7 +786,8 @@ public final class ChatScene implements EventListener, Restorable, KeyboardMappi
|
||||
attachmentView.setVisible(visible);
|
||||
}
|
||||
|
||||
@Event(eventType = OwnStatusChange.class, priority = 50)
|
||||
@Event(OwnStatusChange.class)
|
||||
@Priority(50)
|
||||
private void generateOwnStatusControl() {
|
||||
|
||||
// Update the own user status if present
|
||||
@ -794,7 +798,7 @@ public final class ChatScene implements EventListener, Restorable, KeyboardMappi
|
||||
// Else prepend it to the HBox children
|
||||
final var ownUserControl = new ContactControl(localDB.getUser());
|
||||
ownUserControl.setAlignment(Pos.CENTER_LEFT);
|
||||
HBox.setHgrow(ownUserControl, Priority.NEVER);
|
||||
HBox.setHgrow(ownUserControl, javafx.scene.layout.Priority.NEVER);
|
||||
ownContactControl.getChildren().add(1, ownUserControl);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import javafx.fxml.FXML;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.control.Alert.AlertType;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
import dev.kske.eventbus.core.*;
|
||||
|
||||
import envoy.data.User;
|
||||
import envoy.event.ElementOperation;
|
||||
@ -34,7 +34,7 @@ import envoy.client.ui.listcell.ListCellFactory;
|
||||
* @author Maximilian Käfer
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public class ContactSearchTab implements EventListener {
|
||||
public class ContactSearchTab {
|
||||
|
||||
@FXML
|
||||
private TextArea searchBar;
|
||||
|
@ -10,11 +10,11 @@ import javafx.scene.control.*;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
import dev.kske.eventbus.core.*;
|
||||
|
||||
import envoy.data.*;
|
||||
import envoy.event.GroupCreation;
|
||||
import envoy.event.contact.*;
|
||||
import envoy.event.contact.UserOperation;
|
||||
import envoy.util.Bounds;
|
||||
|
||||
import envoy.client.data.*;
|
||||
@ -33,7 +33,7 @@ import envoy.client.ui.listcell.ListCellFactory;
|
||||
* @author Maximilian Käfer
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public class GroupCreationTab implements EventListener {
|
||||
public class GroupCreationTab {
|
||||
|
||||
@FXML
|
||||
private Button createButton;
|
||||
|
@ -10,7 +10,7 @@ import javafx.scene.control.*;
|
||||
import javafx.scene.control.Alert.AlertType;
|
||||
import javafx.scene.image.ImageView;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
import dev.kske.eventbus.core.*;
|
||||
|
||||
import envoy.data.LoginCredentials;
|
||||
import envoy.event.HandshakeRejection;
|
||||
@ -27,7 +27,7 @@ import envoy.client.util.IconUtil;
|
||||
* @author Maximilian Käfer
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public final class LoginScene implements EventListener {
|
||||
public final class LoginScene {
|
||||
|
||||
@FXML
|
||||
private TextField userTextField;
|
||||
|
@ -2,7 +2,7 @@ package envoy.client.ui.settings;
|
||||
|
||||
import javafx.scene.control.*;
|
||||
|
||||
import dev.kske.eventbus.EventBus;
|
||||
import dev.kske.eventbus.core.EventBus;
|
||||
|
||||
import envoy.data.User.UserStatus;
|
||||
|
||||
|
@ -15,7 +15,7 @@ import javafx.scene.layout.HBox;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import dev.kske.eventbus.EventBus;
|
||||
import dev.kske.eventbus.core.EventBus;
|
||||
|
||||
import envoy.event.*;
|
||||
import envoy.util.*;
|
||||
|
@ -7,7 +7,7 @@ import java.util.logging.*;
|
||||
|
||||
import javafx.stage.FileChooser;
|
||||
|
||||
import dev.kske.eventbus.EventBus;
|
||||
import dev.kske.eventbus.core.EventBus;
|
||||
|
||||
import envoy.data.Message;
|
||||
import envoy.util.EnvoyLog;
|
||||
|
@ -5,7 +5,7 @@ import java.util.logging.*;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.control.Alert.AlertType;
|
||||
|
||||
import dev.kske.eventbus.EventBus;
|
||||
import dev.kske.eventbus.core.EventBus;
|
||||
|
||||
import envoy.data.*;
|
||||
import envoy.data.User.UserStatus;
|
||||
|
@ -16,12 +16,13 @@ module envoy.client {
|
||||
requires javafx.fxml;
|
||||
requires javafx.base;
|
||||
requires javafx.graphics;
|
||||
requires dev.kske.eventbus.core;
|
||||
|
||||
opens envoy.client.ui to javafx.graphics, javafx.fxml, dev.kske.eventbus;
|
||||
opens envoy.client.ui.controller to javafx.graphics, javafx.fxml, envoy.client.util, dev.kske.eventbus;
|
||||
opens envoy.client.ui.chatscene to javafx.graphics, javafx.fxml, envoy.client.util, dev.kske.eventbus;
|
||||
opens envoy.client.ui to javafx.graphics, javafx.fxml, dev.kske.eventbus.core;
|
||||
opens envoy.client.ui.controller to javafx.graphics, javafx.fxml, envoy.client.util, dev.kske.eventbus.core;
|
||||
opens envoy.client.ui.chatscene to javafx.graphics, javafx.fxml, envoy.client.util, dev.kske.eventbus.core;
|
||||
opens envoy.client.ui.control to javafx.graphics, javafx.fxml;
|
||||
opens envoy.client.ui.settings to envoy.client.util;
|
||||
opens envoy.client.net to dev.kske.eventbus;
|
||||
opens envoy.client.data to dev.kske.eventbus;
|
||||
opens envoy.client.net to dev.kske.eventbus.core;
|
||||
opens envoy.client.data to dev.kske.eventbus.core;
|
||||
}
|
||||
|
@ -12,18 +12,11 @@
|
||||
<version>0.2-beta</version>
|
||||
</parent>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>kske-repo</id>
|
||||
<url>https://kske.dev/maven-repo</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.kske</groupId>
|
||||
<artifactId>event-bus</artifactId>
|
||||
<version>0.0.4</version>
|
||||
<artifactId>event-bus-core</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
|
@ -2,15 +2,13 @@ package envoy.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import dev.kske.eventbus.IEvent;
|
||||
|
||||
/**
|
||||
* Generates increasing IDs between two numbers.
|
||||
*
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Common v0.2-alpha
|
||||
*/
|
||||
public final class IDGenerator implements IEvent, Serializable {
|
||||
public final class IDGenerator implements Serializable {
|
||||
|
||||
private final long end;
|
||||
private long current;
|
||||
|
@ -4,8 +4,6 @@ import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
|
||||
import dev.kske.eventbus.IEvent;
|
||||
|
||||
/**
|
||||
* Represents a unique message with a unique, numeric ID. Further metadata includes the sender and
|
||||
* recipient {@link User}s, as well as the creation date and the current {@link MessageStatus}.<br>
|
||||
@ -14,7 +12,7 @@ import dev.kske.eventbus.IEvent;
|
||||
* @author Leon Hofmeister
|
||||
* @since Envoy Common v0.2-alpha
|
||||
*/
|
||||
public class Message implements Serializable, IEvent {
|
||||
public class Message implements Serializable {
|
||||
|
||||
/**
|
||||
* This enumeration defines all possible statuses a {link Message} can have.
|
||||
|
@ -3,18 +3,15 @@ package envoy.event;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
import dev.kske.eventbus.IEvent;
|
||||
|
||||
/**
|
||||
* This class serves as a convenience base class for all events. It implements the {@link IEvent}
|
||||
* interface and provides a generic value. For events without a value there also is
|
||||
* {@link envoy.event.Event.Valueless}.
|
||||
* This class serves as a convenience base class for all events. It provides a generic value. For
|
||||
* events without a value there also is {@link envoy.event.Event.Valueless}.
|
||||
*
|
||||
* @author Kai S. K. Engelbart
|
||||
* @param <T> the type of the Event
|
||||
* @since Envoy v0.2-alpha
|
||||
*/
|
||||
public abstract class Event<T> implements IEvent, Serializable {
|
||||
public abstract class Event<T> implements Serializable {
|
||||
|
||||
protected final T value;
|
||||
|
||||
|
@ -16,5 +16,5 @@ module envoy.common {
|
||||
exports envoy.event.contact;
|
||||
|
||||
requires transitive java.logging;
|
||||
requires transitive dev.kske.eventbus;
|
||||
requires transitive dev.kske.eventbus.core;
|
||||
}
|
||||
|
@ -18,10 +18,10 @@ import envoy.util.SerializationUtils;
|
||||
* @author Leon Hofmeister
|
||||
* @since Envoy Common v0.1-beta
|
||||
*/
|
||||
class UserTest {
|
||||
public class UserTest {
|
||||
|
||||
@Test
|
||||
void test() throws IOException, ClassNotFoundException {
|
||||
public void test() throws IOException, ClassNotFoundException {
|
||||
User user2 = new User(2, "kai");
|
||||
User user3 = new User(3, "ai");
|
||||
User user4 = new User(4, "ki", Set.of(user2, user3));
|
||||
|
7
pom.xml
7
pom.xml
@ -28,6 +28,13 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M5</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<modules>
|
||||
|
@ -40,6 +40,7 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
|
||||
// Cache this write proxy for user-independent notifications
|
||||
UserStatusChangeProcessor.setWriteProxy(writeProxy);
|
||||
|
||||
// Check for compatible versions
|
||||
if (!VersionUtil.verifyCompatibility(credentials.getClientVersion())) {
|
||||
logger.info("The client has the wrong version.");
|
||||
writeProxy.write(socketID, new HandshakeRejection(WRONG_VERSION));
|
||||
@ -70,10 +71,10 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
|
||||
writeProxy.write(socketID, new HandshakeRejection(INVALID_TOKEN));
|
||||
return;
|
||||
}
|
||||
} else
|
||||
} else if (!PasswordUtil.validate(credentials.getPassword(),
|
||||
user.getPasswordHash())) {
|
||||
|
||||
// Check the password hash
|
||||
if (!PasswordUtil.validate(credentials.getPassword(), user.getPasswordHash())) {
|
||||
// Check the password hash
|
||||
logger.info(user + " has entered the wrong password.");
|
||||
writeProxy.write(socketID, new HandshakeRejection(WRONG_PASSWORD_OR_USER));
|
||||
return;
|
||||
@ -101,7 +102,8 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
|
||||
writeProxy.write(socketID, new HandshakeRejection(USERNAME_TAKEN));
|
||||
return;
|
||||
} catch (final NoResultException e) {
|
||||
// Creation of a new user
|
||||
|
||||
// Create a new user
|
||||
user = new User();
|
||||
user.setName(credentials.getIdentifier());
|
||||
user.setLastSeen(Instant.now());
|
||||
@ -138,6 +140,15 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
|
||||
persistenceManager.updateContact(user);
|
||||
writeProxy.write(socketID, new NewAuthToken(token));
|
||||
}
|
||||
|
||||
// Notify the user if a contact deletion has happened since he last logged in
|
||||
if (user.getLatestContactDeletion().isAfter(user.getLastSeen()))
|
||||
writeProxy.write(socketID, new ContactsChangedSinceLastLogin());
|
||||
|
||||
// Complete the handshake
|
||||
writeProxy.write(socketID, user.toCommon());
|
||||
|
||||
// Send pending (group) messages and status changes
|
||||
final var pendingMessages =
|
||||
PersistenceManager.getInstance().getPendingMessages(user, credentials.getLastSync());
|
||||
pendingMessages.removeIf(GroupMessage.class::isInstance);
|
||||
@ -162,8 +173,9 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
|
||||
writeProxy.write(connectionManager.getSocketID(msg.getSender().getID()),
|
||||
new MessageStatusChange(msgCommon));
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
writeProxy.write(socketID, new MessageStatusChange(msgCommon));
|
||||
}
|
||||
}
|
||||
|
||||
final List<GroupMessage> pendingGroupMessages = PersistenceManager.getInstance()
|
||||
@ -197,10 +209,11 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
|
||||
}
|
||||
|
||||
PersistenceManager.getInstance().updateMessage(gmsg);
|
||||
} else
|
||||
} else {
|
||||
|
||||
// Just send the message without updating if it was received in the past
|
||||
writeProxy.write(socketID, gmsgCommon);
|
||||
}
|
||||
} else {
|
||||
|
||||
// Sending group message status changes
|
||||
@ -220,11 +233,5 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
|
||||
writeProxy.write(socketID, new MessageStatusChange(gmsgCommon));
|
||||
}
|
||||
}
|
||||
// Notify the user if a contact deletion has happened since he last logged in
|
||||
if (user.getLatestContactDeletion().isAfter(user.getLastSeen()))
|
||||
writeProxy.write(socketID, new ContactsChangedSinceLastLogin());
|
||||
|
||||
// Complete the handshake
|
||||
writeProxy.write(socketID, user.toCommon());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user