Add Ability to Change the User Status Freely #90
@ -27,8 +27,6 @@ public final class AlertHelper {
|
|||||||
* @since Envoy Client v0.2-beta
|
* @since Envoy Client v0.2-beta
|
||||||
*/
|
*/
|
||||||
public static void confirmAction(Alert alert, Runnable action) {
|
public static void confirmAction(Alert alert, Runnable action) {
|
||||||
alert.setHeight(225);
|
|
||||||
alert.setWidth(400);
|
|
||||||
alert.setHeaderText("");
|
alert.setHeaderText("");
|
||||||
if (Settings.getInstance().isAskForConfirmation()) alert.showAndWait().filter(ButtonType.OK::equals).ifPresent(bu -> action.run());
|
if (Settings.getInstance().isAskForConfirmation()) alert.showAndWait().filter(ButtonType.OK::equals).ifPresent(bu -> action.run());
|
||||||
else action.run();
|
else action.run();
|
||||||
|
@ -14,6 +14,7 @@ import envoy.client.data.Settings;
|
|||||||
import envoy.client.event.*;
|
import envoy.client.event.*;
|
||||||
import envoy.client.helper.ShutdownHelper;
|
import envoy.client.helper.ShutdownHelper;
|
||||||
import envoy.client.util.UserUtil;
|
import envoy.client.util.UserUtil;
|
||||||
|
import envoy.data.User.UserStatus;
|
||||||
import envoy.util.EnvoyLog;
|
import envoy.util.EnvoyLog;
|
||||||
|
|
||||||
import dev.kske.eventbus.*;
|
import dev.kske.eventbus.*;
|
||||||
@ -127,10 +128,23 @@ public final class SceneContext implements EventListener {
|
|||||||
// Add the option to exit Linux-like with "Control" + "Q" or "Alt" + "F4"
|
// Add the option to exit Linux-like with "Control" + "Q" or "Alt" + "F4"
|
||||||
accelerators.put(new KeyCodeCombination(KeyCode.Q, KeyCombination.CONTROL_DOWN), ShutdownHelper::exit);
|
accelerators.put(new KeyCodeCombination(KeyCode.Q, KeyCombination.CONTROL_DOWN), ShutdownHelper::exit);
|
||||||
|
|
||||||
// Add the option to logout using "Control"+"Shift"+"L" if not in login scene
|
if (sceneInfo != SceneInfo.LOGIN_SCENE) {
|
||||||
kske marked this conversation as resolved
|
|||||||
if (sceneInfo != SceneInfo.LOGIN_SCENE)
|
|
||||||
|
// Add the option to logout using "Control"+"Shift"+"L"
|
||||||
accelerators.put(new KeyCodeCombination(KeyCode.L, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN), UserUtil::logout);
|
accelerators.put(new KeyCodeCombination(KeyCode.L, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN), UserUtil::logout);
|
||||||
|
|
||||||
|
// Add the option to change status using "Control" + "Shift" +
|
||||||
|
// (o)F(fline)/ A(way)/ B(usy)/(o)N(line)
|
||||||
|
accelerators.put(new KeyCodeCombination(KeyCode.F, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN),
|
||||||
|
() -> UserUtil.changeStatus(UserStatus.OFFLINE));
|
||||||
|
accelerators.put(new KeyCodeCombination(KeyCode.A, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN),
|
||||||
|
() -> UserUtil.changeStatus(UserStatus.AWAY));
|
||||||
|
accelerators.put(new KeyCodeCombination(KeyCode.B, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN),
|
||||||
|
() -> UserUtil.changeStatus(UserStatus.BUSY));
|
||||||
|
accelerators.put(new KeyCodeCombination(KeyCode.N, KeyCombination.CONTROL_DOWN, KeyCombination.SHIFT_DOWN),
|
||||||
|
() -> UserUtil.changeStatus(UserStatus.ONLINE));
|
||||||
|
}
|
||||||
|
|
||||||
// Add the option to open the settings scene with "Control"+"S", if being in
|
// Add the option to open the settings scene with "Control"+"S", if being in
|
||||||
// chat scene
|
// chat scene
|
||||||
if (sceneInfo == SceneInfo.CHAT_SCENE)
|
if (sceneInfo == SceneInfo.CHAT_SCENE)
|
||||||
|
@ -7,8 +7,9 @@ import javafx.application.Platform;
|
|||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
import envoy.client.helper.ShutdownHelper;
|
import envoy.client.helper.ShutdownHelper;
|
||||||
import envoy.client.util.IconUtil;
|
import envoy.client.util.*;
|
||||||
import envoy.data.Message;
|
import envoy.data.Message;
|
||||||
|
import envoy.data.User.UserStatus;
|
||||||
|
|
||||||
import dev.kske.eventbus.*;
|
import dev.kske.eventbus.*;
|
||||||
import dev.kske.eventbus.Event;
|
import dev.kske.eventbus.Event;
|
||||||
@ -51,12 +52,27 @@ public final class StatusTrayIcon implements EventListener {
|
|||||||
trayIcon.setImageAutoSize(true);
|
trayIcon.setImageAutoSize(true);
|
||||||
trayIcon.setToolTip("You are notified if you have unread messages.");
|
trayIcon.setToolTip("You are notified if you have unread messages.");
|
||||||
|
|
||||||
final PopupMenu popup = new PopupMenu();
|
final var popup = new PopupMenu();
|
||||||
|
|
||||||
final MenuItem exitMenuItem = new MenuItem("Exit");
|
// Adding the exit menu item
|
||||||
|
final var exitMenuItem = new MenuItem("Exit");
|
||||||
exitMenuItem.addActionListener(evt -> ShutdownHelper.exit());
|
exitMenuItem.addActionListener(evt -> ShutdownHelper.exit());
|
||||||
popup.add(exitMenuItem);
|
popup.add(exitMenuItem);
|
||||||
|
|
||||||
|
// Adding the logout menu item
|
||||||
|
final var logoutMenuItem = new MenuItem("Logout");
|
||||||
|
logoutMenuItem.addActionListener(evt -> { hide(); UserUtil.logout(); });
|
||||||
|
popup.add(exitMenuItem);
|
||||||
|
|
||||||
|
// Adding the status change items
|
||||||
|
final var statusSubMenu = new Menu("Change status");
|
||||||
|
for (final var status : UserStatus.values()) {
|
||||||
|
final var statusMenuItem = new MenuItem(status.toString().toLowerCase());
|
||||||
|
statusMenuItem.addActionListener(evt -> UserUtil.changeStatus(status));
|
||||||
|
statusSubMenu.add(statusMenuItem);
|
||||||
|
}
|
||||||
|
popup.add(statusSubMenu);
|
||||||
|
|
||||||
trayIcon.setPopupMenu(popup);
|
trayIcon.setPopupMenu(popup);
|
||||||
|
|
||||||
// Only display messages if the stage is not focused
|
// Only display messages if the stage is not focused
|
||||||
@ -89,9 +105,8 @@ public final class StatusTrayIcon implements EventListener {
|
|||||||
|
|
||||||
@Event
|
@Event
|
||||||
private void onMessage(Message message) {
|
private void onMessage(Message message) {
|
||||||
if (displayMessages) trayIcon.displayMessage(
|
if (displayMessages) trayIcon
|
||||||
message.hasAttachment() ? "New " + message.getAttachment().getType().toString().toLowerCase() + " message received" : "New message received",
|
.displayMessage(message.hasAttachment() ? "New " + message.getAttachment().getType().toString().toLowerCase() + " message received"
|
||||||
message.getText(),
|
: "New message received", message.getText(), MessageType.INFO);
|
||||||
MessageType.INFO);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,8 @@ import java.util.Random;
|
|||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import javafx.scene.control.ListView;
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.control.Alert.AlertType;
|
||||||
import javafx.scene.control.skin.VirtualFlow;
|
import javafx.scene.control.skin.VirtualFlow;
|
||||||
|
|
||||||
import envoy.client.data.Context;
|
import envoy.client.data.Context;
|
||||||
@ -14,6 +15,7 @@ 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.*;
|
||||||
import envoy.data.Message;
|
import envoy.data.Message;
|
||||||
|
import envoy.data.User.UserStatus;
|
||||||
import envoy.util.EnvoyLog;
|
import envoy.util.EnvoyLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,6 +65,17 @@ public final class ChatSceneCommands {
|
|||||||
.setDescription("Opens the settings screen")
|
.setDescription("Opens the settings screen")
|
||||||
.buildNoArg("settings");
|
.buildNoArg("settings");
|
||||||
|
|
||||||
|
// Status change initialization
|
||||||
|
builder.setAction(text -> {
|
||||||
|
try {
|
||||||
|
UserUtil.changeStatus(Enum.valueOf(UserStatus.class, text.get(0).toUpperCase()));
|
||||||
|
} catch (final IllegalArgumentException e) {
|
||||||
|
final var alert = new Alert(AlertType.ERROR);
|
||||||
kske marked this conversation as resolved
kske
commented
We implement a standardized way of handling system command failures. Wou don't be able to display an alert if Envoy is running on the command line. We implement a standardized way of handling system command failures. Wou don't be able to display an alert if Envoy is running on the command line.
delvh
commented
While I agree with you, there is a reason why I accepted your solution of automatically displaying an alert in case of a system command only with gritted teeth. But, I'd say this is a branch of its own again and far beyond the scope of this branch. While I agree with you, there is a reason why I accepted your solution of automatically displaying an alert in case of a system command only with gritted teeth.
For now, this has to suffice. In the future I can well imagine that we can pass a consumer accepting an error to the calling method to handle errors in a command.
But, I'd say this is a branch of its own again and far beyond the scope of this branch.
kske
commented
I would suggest to introduce a new exception and catch that at a convenient place. No need for consumers. I however do agree, that this is beyond the scope of this branch. I would suggest to introduce a new exception and catch that at a convenient place. No need for consumers.
I however do agree, that this is beyond the scope of this branch.
|
|||||||
|
alert.setContentText("Please provide an existing status");
|
||||||
|
alert.showAndWait();
|
||||||
|
}
|
||||||
|
}).setDescription("Changes your status to the given status.").setNumberOfArguments(1).setDefaults("OFFLINE").build("status");
|
||||||
|
|
||||||
// Selection of a new message initialization
|
// Selection of a new message initialization
|
||||||
messageDependantAction("s",
|
messageDependantAction("s",
|
||||||
m -> { messageList.getSelectionModel().clearSelection(); messageList.getSelectionModel().select(m); },
|
m -> { messageList.getSelectionModel().clearSelection(); messageList.getSelectionModel().select(m); },
|
||||||
|
@ -55,7 +55,6 @@ public final class GeneralSettingsPane extends SettingsPane {
|
|||||||
combobox.setOnAction(e -> { settings.setCurrentTheme(combobox.getValue()); EventBus.getInstance().dispatch(new ThemeChangeEvent()); });
|
combobox.setOnAction(e -> { settings.setCurrentTheme(combobox.getValue()); EventBus.getInstance().dispatch(new ThemeChangeEvent()); });
|
||||||
getChildren().add(combobox);
|
getChildren().add(combobox);
|
||||||
|
|
||||||
if (context.getClient().isOnline()) {
|
|
||||||
final var statusComboBox = new ComboBox<UserStatus>();
|
final var statusComboBox = new ComboBox<UserStatus>();
|
||||||
statusComboBox.getItems().setAll(UserStatus.values());
|
statusComboBox.getItems().setAll(UserStatus.values());
|
||||||
statusComboBox.setValue(context.getLocalDB().getUser().getStatus());
|
statusComboBox.setValue(context.getLocalDB().getUser().getStatus());
|
||||||
@ -66,7 +65,6 @@ public final class GeneralSettingsPane extends SettingsPane {
|
|||||||
else UserUtil.changeStatus(status);
|
else UserUtil.changeStatus(status);
|
||||||
});
|
});
|
||||||
getChildren().add(statusComboBox);
|
getChildren().add(statusComboBox);
|
||||||
}
|
|
||||||
|
|
||||||
final var logoutButton = new Button("Logout");
|
final var logoutButton = new Button("Logout");
|
||||||
logoutButton.setOnAction(e -> UserUtil.logout());
|
logoutButton.setOnAction(e -> UserUtil.logout());
|
||||||
|
@ -53,6 +53,7 @@ public final class UserUtil {
|
|||||||
*/
|
*/
|
||||||
public static void changeStatus(UserStatus newStatus) {
|
public static void changeStatus(UserStatus newStatus) {
|
||||||
EventBus.getInstance().dispatch(new OwnStatusChange(newStatus));
|
EventBus.getInstance().dispatch(new OwnStatusChange(newStatus));
|
||||||
|
if (Context.getInstance().getClient().isOnline())
|
||||||
Context.getInstance().getClient().send(new UserStatusChange(Context.getInstance().getLocalDB().getUser().getID(), newStatus));
|
Context.getInstance().getClient().send(new UserStatusChange(Context.getInstance().getLocalDB().getUser().getID(), newStatus));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user
SceneContext
, that could be completely generic as to what scenes it displays, except for being littered with code specific toLoginScene
which nobody would expect here?(yes, these are both rhetorical questions)
to 1. While I know what you mean, I'd still say that this goes beyond the scope of this branch.
to 2. While I know what you mean, I'd still say that this goes beyond the scope of this branch.
It seems as if one of the next branches should cleanup that in SceneContext. I could do it in that branch, but than this branch will have two completely separate tasks on it (and it would be eve larger than it already is).
No, I think you are right. The cleanup should be performed inside a separate branch.
See #91