feat(messages): possibilité de modifier ou supprimer un message

This commit is contained in:
Emi Boucly 2025-02-12 12:44:17 +01:00
parent cbbb95f6d5
commit bf1a52f368
8 changed files with 210 additions and 4 deletions

View file

@ -16,6 +16,7 @@ import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
@ -61,7 +62,7 @@ public class ChatController implements Initializable {
public ToggleButton connectionButton;
public ImageView avatarImageView;
public SplitPane exchangeSplitPane;
public ListView postListView;
public ListView<Post> postListView;
public ListView<Room> roomsListView;
public ListView<Contact> contactsListView;
public TextField messageTextField;
@ -81,6 +82,11 @@ public class ChatController implements Initializable {
private ResourceBundle i18nBundle;
private Properties properties = new Properties();
private Vector<String> hostlist;
private ContextMenu contextMenu = new ContextMenu();
private MenuItem removeMenuItem;
private MenuItem editMenuItem;
private MenuItem cancelMenuItem;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
@ -139,6 +145,9 @@ public class ChatController implements Initializable {
sendButton.setOnAction(this::onActionSend);
messageTextField.setOnAction(this::onActionSend);
initContextMenu();
postListView.setOnContextMenuRequested(this::handleContextMenu);
initContactListView();
initPostListView();
initRoomListView();
@ -164,6 +173,58 @@ public class ChatController implements Initializable {
}
private void handleContextMenu(ContextMenuEvent e) {
if (postListView.getSelectionModel().getSelectedItem().getFrom().equals(contact.getLogin())) {
contextMenu.show(postListView, e.getScreenX(), e.getScreenY());
}
}
private void initContextMenu() {
this.removeMenuItem = new MenuItem();
this.editMenuItem = new MenuItem();
this.cancelMenuItem = new MenuItem();
removeMenuItem.setText("Remove message");
editMenuItem.setText("Edit message");
cancelMenuItem.setText("Cancel");
removeMenuItem.setOnAction(this::onMessageRemove);
editMenuItem.setOnAction(this::onMessageEdit);
cancelMenuItem.setOnAction(e -> contextMenu.hide());
contextMenu.getItems().addAll(removeMenuItem, editMenuItem, cancelMenuItem);
}
private void onMessageEdit(ActionEvent actionEvent) {
UUID postUUID = postListView.getSelectionModel().getSelectedItem().getId();
long timestamp = postListView.getSelectionModel().getSelectedItem().getTimestamp();
String from = postListView.getSelectionModel().getSelectedItem().getFrom();
String to = postListView.getSelectionModel().getSelectedItem().getTo();
try {
ModifyMessageController controller = showNewStage(i18nBundle.getString("messageEdit"), "modifymessage-view.fxml");
Post post = new Post(postUUID, timestamp, from, to, controller.hostTextField.getText());
client.sendPostEvent(post);
postVector.remove(postListView.getSelectionModel().getSelectedItem());
postsObservableList.remove(postListView.getSelectionModel().getSelectedItem());
postListView.refresh();
} catch (IOException e) {
LOGGER.warning("Can't open modify message view!");
}
}
private void onMessageRemove(ActionEvent actionEvent) {
UUID postUUID = postListView.getSelectionModel().getSelectedItem().getId();
long timestamp = postListView.getSelectionModel().getSelectedItem().getTimestamp();
String from = postListView.getSelectionModel().getSelectedItem().getFrom();
String to = postListView.getSelectionModel().getSelectedItem().getTo();
client.sendPostEvent(new Post(postUUID, timestamp, from, to, "Ce message a été supprimé."));
postVector.remove(postListView.getSelectionModel().getSelectedItem());
postsObservableList.remove(postListView.getSelectionModel().getSelectedItem());
postListView.refresh();
}
private void handleHostAdd(ActionEvent actionEvent) {
try {
ChatHostAddController controller = showNewStage(i18nBundle.getString("addHost"), "chathostadd-view.fxml");
@ -482,15 +543,21 @@ public class ChatController implements Initializable {
LOGGER.info("New message to contact!");
if (contactsListView.getSelectionModel().getSelectedItem().getLogin().equals(content.getString("to"))) {
LOGGER.info("New message! to:dm, from:" + content.getString("from"));
postVector.remove(Post.fromJson(content));
postsObservableList.remove(Post.fromJson(content));
postVector.add(Post.fromJson(content));
postsObservableList.add(Post.fromJson(content));
postListView.refresh();
}
if (contact.getLogin().equals(content.getString("to"))) {
if (contactsListView.getSelectionModel().getSelectedItem().getLogin().equals(content.getString("from"))) {
LOGGER.info("New message! to:dm, from:myself");
postVector.remove(Post.fromJson(content));
postsObservableList.remove(Post.fromJson(content));
postVector.add(Post.fromJson(content));
postsObservableList.add(Post.fromJson(content));
postListView.refresh();
} else {
@ -505,8 +572,11 @@ public class ChatController implements Initializable {
LOGGER.info("New message to room!");
if (roomsListView.getSelectionModel().getSelectedItem().getRoomName().equals(content.getString("to"))) {
LOGGER.info("New message! to:room, from:myself");
postVector.remove(Post.fromJson(content));
postsObservableList.remove(Post.fromJson(content));
postVector.add(Post.fromJson(content));
postsObservableList.add(Post.fromJson(content));
postListView.refresh();
} else {
roomMap.get(content.getString("to")).getUnreadCount().incrementUnreadCount();
@ -525,6 +595,15 @@ public class ChatController implements Initializable {
contactsListView.refresh();
LOGGER.info("New message to contact + nothing sel");
}
} finally {
postListView.getItems().sort((o1,o2)->{
if(o1.equals(o2)) return 0;
if(o1.getTimestamp() > o2.getTimestamp())
return 1;
else
return 0;
});
postListView.refresh();
}
}
private void handleContEvent(JSONObject content) {

View file

@ -0,0 +1,41 @@
package rtgre.chat;
import javafx.event.ActionEvent;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import java.net.URL;
import java.util.ResourceBundle;
public class ModifyMessageController implements Initializable {
public TextField hostTextField;
public Button resetButton;
public Button submitButton;
private Boolean ok;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
resetButton.setOnAction(this::onActionReset);
submitButton.setOnAction(this::onActionSubmit);
hostTextField.setOnAction(this::onActionSubmit);
}
private void onActionReset(ActionEvent actionEvent) {
hostTextField.setText("");
}
private void onActionSubmit(ActionEvent actionEvent) {
ok = true;
((Stage) submitButton.getScene().getWindow()).close();
}
public boolean isOk() {
return ok;
}
}

View file

@ -6,6 +6,7 @@ import rtgre.chat.ChatController;
import rtgre.modeles.Contact;
import rtgre.modeles.Event;
import rtgre.modeles.Message;
import rtgre.modeles.Post;
import java.io.BufferedReader;
import java.io.IOException;
@ -112,4 +113,9 @@ public class ChatClient extends ClientTCP {
public void sendMessageEvent(Message msg) {
sendEvent(new Event("MESG", msg.toJsonObject()));
}
public void sendPostEvent(Post selectedItem) {
Event postEvent = new Event(Event.POST, selectedItem.toJsonObject());
sendEvent(postEvent);
}
}

View file

@ -90,6 +90,21 @@ public class DatabaseApi {
}
}
public boolean removePost(Post post) {
String query = "DELETE FROM posts WHERE id=?";
try {
PreparedStatement pstmt = con.prepareStatement(query);
pstmt.setString(1, post.getId().toString());
pstmt.executeUpdate();
return true;
} catch (SQLException e) {
LOGGER.severe("Cannot remove post!");
System.out.println(e.getMessage());
e.printStackTrace();;
return false;
}
}
public void close() {
try {
con.close();

View file

@ -158,7 +158,7 @@ public class ChatServer {
return contactMap;
}
/** Temporaire : connecte daisy pour test */
/** Temporaire : connecte pour test */
public static void daisyConnect() throws IOException {
ChatClient client = new ChatClient("localhost", 2024, null);
client.sendAuthEvent(new Contact("daisy", null));
@ -282,12 +282,27 @@ public class ChatServer {
doCont(event.getContent());
LOGGER.info("Update de contact");
return true;
} else if (event.getType().equals(Event.POST)) {
doPost(event.getContent());
LOGGER.info("Post edited");
return true;
} else {
LOGGER.warning("Unhandled event type: " + event.getType());
return false;
}
}
private void doPost(JSONObject content) {
database = new DatabaseApi();
database.removePost(Post.fromJson(content));
database.addPost(Post.fromJson(content));
database.close();
postVector.removeIf(post -> post.getId().equals(Post.fromJson(content).getId()));
postVector.add(Post.fromJson(content));
sendEventToAllContacts(new Event(Event.POST, content));
LOGGER.info("didpost");
}
private void doCont(JSONObject content) {
if (user.isConnected()) {
sendEventToAllContacts(new Event("CONT", content));

View file

@ -23,3 +23,4 @@ submit=Submit
systemError=Login cannot be system
systemHelloContact=Welcome in the discussion with
systemHelloRoom=Welcome in room
messageEdit=Modify message...

View file

@ -23,3 +23,4 @@ submit=Valider
systemError=Le login ne peut pas être system
systemHelloContact=Bienvenue dans la discussion avec
systemHelloRoom=Bienvenue dans le salon
messageEdit=Modifier un message...

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="rtgre.chat.ModifyMessageController">
<children>
<GridPane prefWidth="400.0">
<columnConstraints>
<ColumnConstraints hgrow="NEVER" maxWidth="289.0" minWidth="10.0" prefWidth="82.40000190734864" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="536.0000076293945" minWidth="10.0" prefWidth="307.99999809265137" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="Message :" />
<TextField fx:id="hostTextField" prefWidth="200.0" GridPane.columnIndex="1" />
</children>
<padding>
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
</padding>
<VBox.margin>
<Insets bottom="15.0" />
</VBox.margin>
</GridPane>
<HBox alignment="TOP_CENTER" spacing="10.0">
<children>
<Button fx:id="resetButton" mnemonicParsing="false" prefWidth="100.0" text="%reset" />
<HBox fx:id="submitWrapper">
<children>
<Button fx:id="submitButton" mnemonicParsing="false" prefWidth="100.0" text="%submit" />
</children>
</HBox>
</children>
</HBox>
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</VBox>