From 0be5d0e12a3e0d90d827cb4b3430550667e67844 Mon Sep 17 00:00:00 2001 From: delvh Date: Tue, 29 Sep 2020 00:28:06 +0200 Subject: [PATCH] Added CLI options to copy, delete or save attachm. of selected messages --- .../client/ui/control/MessageControl.java | 77 +++---------- .../envoy/client/ui/controller/ChatScene.java | 24 +++- .../java/envoy/client/util/MessageUtil.java | 105 ++++++++++++++++++ 3 files changed, 138 insertions(+), 68 deletions(-) create mode 100644 client/src/main/java/envoy/client/util/MessageUtil.java diff --git a/client/src/main/java/envoy/client/ui/control/MessageControl.java b/client/src/main/java/envoy/client/ui/control/MessageControl.java index 53aa962..15759be 100644 --- a/client/src/main/java/envoy/client/ui/control/MessageControl.java +++ b/client/src/main/java/envoy/client/ui/control/MessageControl.java @@ -1,8 +1,6 @@ package envoy.client.ui.control; -import java.awt.Toolkit; -import java.awt.datatransfer.StringSelection; -import java.io.*; +import java.io.ByteArrayInputStream; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.Map; @@ -12,19 +10,14 @@ import javafx.geometry.*; import javafx.scene.control.*; import javafx.scene.image.*; import javafx.scene.layout.*; -import javafx.stage.FileChooser; import envoy.client.data.*; import envoy.client.net.Client; -import envoy.client.ui.SceneContext; -import envoy.client.util.IconUtil; +import envoy.client.util.*; import envoy.data.*; import envoy.data.Message.MessageStatus; -import envoy.event.MessageDeletion; import envoy.util.EnvoyLog; -import dev.kske.eventbus.EventBus; - /** * This class transforms a single {@link Message} into a UI component. * @@ -36,15 +29,13 @@ public final class MessageControl extends Label { private final boolean ownMessage; - private final LocalDB localDB = context.getLocalDB(); - private final SceneContext sceneContext = context.getSceneContext(); - private final Client client = context.getClient(); + private final LocalDB localDB = context.getLocalDB(); + private final Client client = context.getClient(); private static final Context context = Context.getInstance(); private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss") .withZone(ZoneId.systemDefault()); private static final Map statusImages = IconUtil.loadByEnum(MessageStatus.class, 16); - private static final Settings settings = Settings.getInstance(); private static final Logger logger = EnvoyLog.getLogger(MessageControl.class); /** @@ -79,14 +70,16 @@ public final class MessageControl extends Label { final var items = contextMenu.getItems(); // Copy message action - final var copyMenuItem = new MenuItem("Copy Text"); - copyMenuItem.setOnAction(e -> copyMessageText(message.getText())); - items.add(copyMenuItem); + if (!message.getText().isEmpty()) { + final var copyMenuItem = new MenuItem("Copy Text"); + copyMenuItem.setOnAction(e -> MessageUtil.copyMessageText(message)); + items.add(copyMenuItem); + } // Delete message - if own message - action if (ownMessage && client.isOnline()) { final var deleteMenuItem = new MenuItem("Delete"); - deleteMenuItem.setOnAction(e -> deleteMessage(message)); + deleteMenuItem.setOnAction(e -> MessageUtil.deleteMessage(message)); items.add(deleteMenuItem); } @@ -96,12 +89,12 @@ public final class MessageControl extends Label { // Forward menu item final var forwardMenuItem = new MenuItem("Forward"); - forwardMenuItem.setOnAction(e -> forwardMessage(message)); + forwardMenuItem.setOnAction(e -> MessageUtil.forwardMessage(message)); items.add(forwardMenuItem); // Quote menu item final var quoteMenuItem = new MenuItem("Quote"); - quoteMenuItem.setOnAction(e -> quoteMessage(message)); + quoteMenuItem.setOnAction(e -> MessageUtil.quoteMessage(message)); items.add(quoteMenuItem); } @@ -127,7 +120,7 @@ public final class MessageControl extends Label { break; } final var saveAttachment = new MenuItem("Save attachment"); - saveAttachment.setOnAction(e -> saveAttachment(message)); + saveAttachment.setOnAction(e -> MessageUtil.saveAttachment(message)); items.add(saveAttachment); } // Creating the textLabel @@ -155,52 +148,8 @@ public final class MessageControl extends Label { setGraphic(vbox); } - // Context Menu actions - - private void copyMessageText(String text) { - logger.log(Level.FINEST, "A copy of message text \"" + text + "\" was requested"); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(text), null); - } - - private void deleteMessage(Message message) { - final var messageDeletionEvent = new MessageDeletion(message.getID()); - messageDeletionEvent.setOwnEvent(); - - // Removing the message locally - EventBus.getInstance().dispatch(messageDeletionEvent); - - // Removing the message on the server and this chat's recipients - Context.getInstance().getClient().send(messageDeletionEvent); - logger.log(Level.FINEST, "message deletion was requested for " + message); - } - - private void forwardMessage(Message message) { logger.log(Level.FINEST, "message forwarding was requested for " + message); } - - private void quoteMessage(Message message) { logger.log(Level.FINEST, "message quotation was requested for " + message); } - private void loadMessageInfoScene(Message message) { logger.log(Level.FINEST, "message info scene was requested for " + message); } - private void saveAttachment(Message message) { - File file; - final var fileName = message.getAttachment().getName(); - final var downloadLocation = settings.getDownloadLocation(); - // Show save file dialog, if the user did not opt-out - if (!settings.isDownloadSavedWithoutAsking()) { - final var fileChooser = new FileChooser(); - fileChooser.setInitialFileName(fileName); - fileChooser.setInitialDirectory(downloadLocation); - file = fileChooser.showSaveDialog(sceneContext.getStage()); - } else file = new File(downloadLocation, fileName); - - // A file was selected - if (file != null) try (FileOutputStream fos = new FileOutputStream(file)) { - fos.write(message.getAttachment().getData()); - logger.log(Level.FINE, "Attachment of message was saved at " + file.getAbsolutePath()); - } catch (final IOException e) { - logger.log(Level.WARNING, "Could not save attachment of " + message + ": ", e); - } - } - /** * @return whether the message stored by this {@code MessageControl} has been * sent by this user of Envoy 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 04332f0..b19a068 100644 --- a/client/src/main/java/envoy/client/ui/controller/ChatScene.java +++ b/client/src/main/java/envoy/client/ui/controller/ChatScene.java @@ -310,11 +310,9 @@ public final class ChatScene implements EventListener, Restorable { @Event(priority = 200) private void onMessageDeletion(MessageDeletion message) { - + // Clearing the selection if the own user was the sender of this event - if (message.isOwnEvent()) Platform.runLater(() -> { - messageList.getSelectionModel().clearSelection(); - }); + if (message.isOwnEvent()) Platform.runLater(() -> { messageList.getSelectionModel().clearSelection(); }); } /** @@ -345,6 +343,24 @@ public final class ChatScene implements EventListener, Restorable { .setNumberOfArguments(0) .setDescription("Opens the settings screen") .build("settings"); + + // Copy text of selection initialization + builder.setAction(text -> { + final var selectedMessage = messageList.getSelectionModel().getSelectedItem(); + if (selectedMessage != null) MessageUtil.copyMessageText(selectedMessage); + }).setNumberOfArguments(0).setDescription("Copies the text of the currently selected message").build("cp-s"); + + // Delete selection initialization + builder.setAction(text -> { + final var selectedMessage = messageList.getSelectionModel().getSelectedItem(); + if (selectedMessage != null) MessageUtil.deleteMessage(selectedMessage); + }).setNumberOfArguments(0).setDescription("Deletes the currently selected message").build("del-s"); + + // Save attachment of selection initialization + builder.setAction(text -> { + final var selectedMessage = messageList.getSelectionModel().getSelectedItem(); + if (selectedMessage != null && selectedMessage.hasAttachment()) MessageUtil.saveAttachment(selectedMessage); + }).setNumberOfArguments(0).setDescription("Copies the text of the currently selected message").build("save-a-s"); } @Override diff --git a/client/src/main/java/envoy/client/util/MessageUtil.java b/client/src/main/java/envoy/client/util/MessageUtil.java new file mode 100644 index 0000000..8d07d54 --- /dev/null +++ b/client/src/main/java/envoy/client/util/MessageUtil.java @@ -0,0 +1,105 @@ +package envoy.client.util; + +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.io.*; +import java.util.logging.*; + +import javafx.stage.FileChooser; + +import envoy.client.data.*; +import envoy.data.Message; +import envoy.event.MessageDeletion; +import envoy.util.EnvoyLog; + +import dev.kske.eventbus.EventBus; + +/** + * Contains methods that are commonly used for {@link Message}s. + * + * @author Leon Hofmeister + * @since Envoy Client v0.3-beta + */ +public class MessageUtil { + + private MessageUtil() {} + + private static Logger logger = EnvoyLog.getLogger(MessageUtil.class); + + /** + * Copies the text of the given message to the System Clipboard. + * + * @param message the message whose text to copy + * @since Envoy Client v0.3-beta + */ + public static void copyMessageText(Message message) { + logger.log(Level.FINEST, "A copy of message text \"" + message.getText() + "\" was requested"); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(message.getText()), null); + } + + /** + * Deletes the given message. + * + * @param message the message to delete + * @since Envoy Client v0.3-beta + */ + public static void deleteMessage(Message message) { + final var messageDeletionEvent = new MessageDeletion(message.getID()); + messageDeletionEvent.setOwnEvent(); + + // Removing the message locally + EventBus.getInstance().dispatch(messageDeletionEvent); + + // Removing the message on the server and this chat's recipients + Context.getInstance().getClient().send(messageDeletionEvent); + logger.log(Level.FINEST, "message deletion was requested for " + message); + } + + /** + * Forwards the given message. + * Currently not implemented. + * + * @param message the message to forward + * @since Envoy Client v0.3-beta + */ + public static void forwardMessage(Message message) { logger.log(Level.FINEST, "message forwarding was requested for " + message); } + + /**selected + * Quotes the given message. + * Currently not implemented. + * + * @param message the message to quote + * @since Envoy Client v0.3-beta + */ + public static void quoteMessage(Message message) { logger.log(Level.FINEST, "message quotation was requested for " + message); } + + /** + * Saves the attachment of a message, if present. + * + * @param message the message whose attachment to save + * @throws IllegalStateException if no attachment is present in the message + * @since Envoy Client v0.3-beta + */ + public static void saveAttachment(Message message) { + if (!message.hasAttachment()) throw new IllegalStateException("Cannot save a non-existing attachment"); + File file; + final var fileName = message.getAttachment().getName(); + final var downloadLocation = Settings.getInstance().getDownloadLocation(); + + // Show save file dialog, if the user did not opt-out + if (!Settings.getInstance().isDownloadSavedWithoutAsking()) { + final var fileChooser = new FileChooser(); + fileChooser.setInitialFileName(fileName); + fileChooser.setInitialDirectory(downloadLocation); + file = fileChooser.showSaveDialog(Context.getInstance().getSceneContext().getStage()); + } else file = new File(downloadLocation, fileName); + + // A file was selected + if (file != null) try (FileOutputStream fos = new FileOutputStream(file)) { + fos.write(message.getAttachment().getData()); + logger.log(Level.FINE, "Attachment of message was saved at " + file.getAbsolutePath()); + } catch (final IOException e) { + logger.log(Level.WARNING, "Could not save attachment of " + message + ": ", e); + } + } +}