diff --git a/client/src/main/java/envoy/client/data/LocalDB.java b/client/src/main/java/envoy/client/data/LocalDB.java index 374b750..524d086 100644 --- a/client/src/main/java/envoy/client/data/LocalDB.java +++ b/client/src/main/java/envoy/client/data/LocalDB.java @@ -7,7 +7,7 @@ import java.time.Instant; import java.util.*; import java.util.logging.Level; -import envoy.client.event.EnvoyCloseEvent; +import envoy.client.event.*; import envoy.data.*; import envoy.event.*; import envoy.exception.EnvoyException; @@ -213,11 +213,19 @@ public final class LocalDB implements EventListener { private void onNewAuthToken(NewAuthToken evt) { authToken = evt.get(); } /** - * Deletes the file that stores the "remember me" feature. + * Deletes all associations to the current user. * * @since Envoy Client v0.2-beta */ - public void deleteLoginFile() { lastLoginFile.delete(); } + @Event(eventType = Logout.class, priority = 100) + public void onLogout() { + lastLoginFile.delete(); + userFile = null; + user = null; + authToken = null; + chats.clear(); + cacheMap = new CacheMap(); + } /** * @return a {@code Map} of all users stored locally with their diff --git a/client/src/main/java/envoy/client/event/Logout.java b/client/src/main/java/envoy/client/event/Logout.java new file mode 100644 index 0000000..e845fb1 --- /dev/null +++ b/client/src/main/java/envoy/client/event/Logout.java @@ -0,0 +1,14 @@ +package envoy.client.event; + +import envoy.event.Event.Valueless; + +/** + * Indicates that a logout has been requested. + * + * @author leon + * @since Envoy Client v0.2-beta + */ +public class Logout extends Valueless { + + private static final long serialVersionUID = 1L; +} diff --git a/client/src/main/java/envoy/client/helper/ShutdownHelper.java b/client/src/main/java/envoy/client/helper/ShutdownHelper.java index 6933c06..812c518 100644 --- a/client/src/main/java/envoy/client/helper/ShutdownHelper.java +++ b/client/src/main/java/envoy/client/helper/ShutdownHelper.java @@ -1,11 +1,11 @@ package envoy.client.helper; -import javafx.application.Platform; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import envoy.client.data.*; -import envoy.client.event.EnvoyCloseEvent; +import envoy.client.event.*; +import envoy.client.ui.SceneContext.SceneInfo; import dev.kske.eventbus.EventBus; @@ -25,21 +25,31 @@ public class ShutdownHelper { * * @since Envoy Client v0.2-beta */ - public static void exit() { exit(Settings.getInstance().isHideOnClose(), true); } - - /** - * Exits the currently open Envoy application or minimizes it. - * Does not necessarily shutdown VM. - * - * @param minimize whether Envoy should be minimized instead of closed - * @param shutdownVM whether the JVM should shutdown - * @since Envoy Client v0.2-beta - */ - public static void exit(boolean minimize, boolean shutdownVM) { - if (minimize) Context.getInstance().getStage().setIconified(true); + public static void exit() { + if (Settings.getInstance().isHideOnClose()) Context.getInstance().getStage().setIconified(true); else { - EventBus.getInstance().dispatch(new EnvoyCloseEvent()); - if (shutdownVM) System.exit(0); + final var alert = new Alert(AlertType.CONFIRMATION); + alert.setTitle("Exit?"); + alert.setContentText("Are you sure you want to exit Envoy?"); + AlertHelper.confirmAction(alert, () -> { EventBus.getInstance().dispatch(new EnvoyCloseEvent()); System.exit(0); }); } } + + /** + * Logs the current user out and reopens + * {@link envoy.client.ui.controller.LoginScene}. + * + * @since Envoy Client v0.2-beta + */ + public static void logout() { + final var alert = new Alert(AlertType.CONFIRMATION); + alert.setTitle("Logout?"); + alert.setContentText("Are you sure you want to log out?"); + + AlertHelper.confirmAction(alert, () -> { + EventBus.getInstance().dispatch(new EnvoyCloseEvent()); + EventBus.getInstance().dispatch(new Logout()); + Context.getInstance().getSceneContext().load(SceneInfo.LOGIN_SCENE); + }); + } } diff --git a/client/src/main/java/envoy/client/net/Client.java b/client/src/main/java/envoy/client/net/Client.java index f2987b3..b2247b3 100644 --- a/client/src/main/java/envoy/client/net/Client.java +++ b/client/src/main/java/envoy/client/net/Client.java @@ -240,7 +240,10 @@ public final class Client implements EventListener, Closeable { logger.log(Level.INFO, "Closing connection..."); try { socket.close(); - } catch (final IOException e) {} + online = false; + } catch (final IOException e) { + logger.log(Level.WARNING, "Failed to close socket: ", e); + } } } diff --git a/client/src/main/java/envoy/client/ui/SceneContext.java b/client/src/main/java/envoy/client/ui/SceneContext.java index 9b72f8e..c37b51d 100644 --- a/client/src/main/java/envoy/client/ui/SceneContext.java +++ b/client/src/main/java/envoy/client/ui/SceneContext.java @@ -108,8 +108,16 @@ public final class SceneContext implements EventListener { sceneStack.push(scene); stage.setScene(scene); - // Adding the option to exit Linux-like with "Control" + "Q" + // Add the option to exit Linux-like with "Control" + "Q" scene.getAccelerators().put(new KeyCodeCombination(KeyCode.Q, KeyCombination.CONTROL_DOWN), ShutdownHelper::exit); + // Add the option to logout using "Control"+"Shift"+"L" + scene.getAccelerators() + .put(new KeyCodeCombination(KeyCode.L, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN), ShutdownHelper::logout); + + // Add the option to open the settings scene with "Control"+"S", if being in + // chat scene + if (sceneInfo.equals(SceneInfo.CHAT_SCENE)) + scene.getAccelerators().put(new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN), () -> load(SceneInfo.SETTINGS_SCENE)); // 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 diff --git a/client/src/main/java/envoy/client/ui/Startup.java b/client/src/main/java/envoy/client/ui/Startup.java index 8b239d3..1bbc7b6 100644 --- a/client/src/main/java/envoy/client/ui/Startup.java +++ b/client/src/main/java/envoy/client/ui/Startup.java @@ -56,6 +56,8 @@ public final class Startup extends Application { */ @Override public void start(Stage stage) throws Exception { + + // Initialize config and logger try { config.loadAll(Startup.class, "client.properties", getParameters().getRaw().toArray(new String[0])); EnvoyLog.initialize(config); @@ -68,7 +70,7 @@ public final class Startup extends Application { // Initialize the local database try { - var localDBFile = new File(config.getHomeDirectory(), config.getServer()); + final var localDBFile = new File(config.getHomeDirectory(), config.getServer()); logger.info("Initializing LocalDB at " + localDBFile); localDB = new LocalDB(localDBFile); } catch (IOException | EnvoyException e) { diff --git a/client/src/main/java/envoy/client/ui/controller/ChatScene.java b/client/src/main/java/envoy/client/ui/controller/ChatScene.java index d9b7412..834c26c 100644 --- a/client/src/main/java/envoy/client/ui/controller/ChatScene.java +++ b/client/src/main/java/envoy/client/ui/controller/ChatScene.java @@ -28,8 +28,10 @@ import envoy.client.data.*; import envoy.client.data.audio.AudioRecorder; import envoy.client.data.commands.*; import envoy.client.event.*; +import envoy.client.helper.ShutdownHelper; import envoy.client.net.*; import envoy.client.ui.*; +import envoy.client.ui.SceneContext.SceneInfo; import envoy.client.ui.custom.TextInputContextMenu; import envoy.client.ui.listcell.*; import envoy.client.util.ReflectionUtil; @@ -338,6 +340,19 @@ public final class ChatScene implements EventListener, Restorable { .setDescription("See for yourself :)") .setNumberOfArguments(2) .build("dabr"); + + // Logout initialization + builder.setAction(text -> ShutdownHelper.logout()).setNumberOfArguments(0).setDescription("Logs you out.").build("logout"); + + // Exit initialization + builder.setAction(text -> ShutdownHelper.exit()).setNumberOfArguments(0).setDescription("Exits the program").build("exit", false); + builder.build("q"); + + // Open settings scene initialization + builder.setAction(text -> sceneContext.load(SceneInfo.SETTINGS_SCENE)) + .setNumberOfArguments(0) + .setDescription("Opens the settings screen") + .build("settings"); } @Override diff --git a/client/src/main/java/envoy/client/ui/settings/GeneralSettingsPane.java b/client/src/main/java/envoy/client/ui/settings/GeneralSettingsPane.java index 4e0a428..e0bf1a5 100644 --- a/client/src/main/java/envoy/client/ui/settings/GeneralSettingsPane.java +++ b/client/src/main/java/envoy/client/ui/settings/GeneralSettingsPane.java @@ -3,7 +3,8 @@ package envoy.client.ui.settings; import javafx.scene.control.*; import envoy.client.data.SettingsItem; -import envoy.client.event.*; +import envoy.client.event.ThemeChangeEvent; +import envoy.client.helper.ShutdownHelper; import envoy.data.User.UserStatus; import dev.kske.eventbus.EventBus; @@ -61,5 +62,12 @@ public final class GeneralSettingsPane extends SettingsPane { // TODO add action when value is changed statusComboBox.setOnAction(e -> {}); getChildren().add(statusComboBox); + + final var logoutButton = new Button("Logout"); + logoutButton.setOnAction(e -> ShutdownHelper.logout()); + final var logoutTooltip = new Tooltip("Brings you back to the login screen and removes \"remember me\" status from this account"); + logoutTooltip.setWrapText(true); + logoutButton.setTooltip(logoutTooltip); + getChildren().add(logoutButton); } }