diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index e97c674f..3a72bbf1 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -4,6 +4,7 @@ module org.example.petshopdesktop { requires javafx.web; requires java.sql; requires java.net.http; + requires java.prefs; requires com.fasterxml.jackson.databind; requires com.fasterxml.jackson.core; requires com.fasterxml.jackson.annotation; diff --git a/src/main/java/org/example/petshopdesktop/api/ChatRealtimeClient.java b/src/main/java/org/example/petshopdesktop/api/ChatRealtimeClient.java index da6d94c3..fcb93c0c 100644 --- a/src/main/java/org/example/petshopdesktop/api/ChatRealtimeClient.java +++ b/src/main/java/org/example/petshopdesktop/api/ChatRealtimeClient.java @@ -37,6 +37,7 @@ public class ChatRealtimeClient implements WebSocket.Listener { private Consumer conversationListener; private Consumer messageListener; private Consumer statusListener; + private volatile String currentStatus = "Chat disconnected"; private ChatRealtimeClient() { this.httpClient = HttpClient.newBuilder() @@ -58,6 +59,9 @@ public class ChatRealtimeClient implements WebSocket.Listener { public void setStatusListener(Consumer statusListener) { this.statusListener = statusListener; + if (statusListener != null) { + statusListener.accept(currentStatus); + } } public void connect() { @@ -286,6 +290,7 @@ public class ChatRealtimeClient implements WebSocket.Listener { } private void publishStatus(String status) { + currentStatus = status; if (statusListener != null) { statusListener.accept(status); } diff --git a/src/main/java/org/example/petshopdesktop/controllers/ChatController.java b/src/main/java/org/example/petshopdesktop/controllers/ChatController.java index 6911960d..3a877ef0 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/ChatController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/ChatController.java @@ -6,6 +6,7 @@ import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.Label; +import javafx.scene.control.TextInputDialog; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.control.ScrollPane; @@ -31,6 +32,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.prefs.Preferences; public class ChatController { private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("MMM d, HH:mm"); @@ -59,6 +61,8 @@ public class ChatController { @FXML private Label lblChatStatus; + private static final Preferences CHAT_PREFERENCES = Preferences.userNodeForPackage(ChatController.class); + private final ObservableList conversations = FXCollections.observableArrayList(); private final Map customerLabels = new HashMap<>(); private final ChatRealtimeClient realtimeClient = ChatRealtimeClient.getInstance(); @@ -107,7 +111,7 @@ public class ChatController { realtimeClient.setConversationListener(conversation -> Platform.runLater(() -> upsertConversation(conversation))); realtimeClient.setMessageListener(message -> Platform.runLater(() -> appendMessageIfSelected(message))); realtimeClient.setStatusListener(status -> Platform.runLater(() -> lblChatStatus.setText(status))); - realtimeClient.connect(); + realtimeClient.subscribeToConversations(); loadCustomers(); loadConversations(); @@ -121,6 +125,35 @@ public class ChatController { } } + @FXML + void lblConversationTitleClicked() { + if (selectedConversation == null) { + return; + } + + TextInputDialog dialog = new TextInputDialog(getConversationTitle(selectedConversation)); + dialog.setTitle("Rename Conversation"); + dialog.setHeaderText("Rename this conversation"); + dialog.setContentText("Title:"); + dialog.getEditor().setTextFormatter(new javafx.scene.control.TextFormatter(change -> change.getControlNewText().length() <= 60 ? change : null)); + + Optional result = dialog.showAndWait(); + if (result.isEmpty()) { + return; + } + + String alias = result.get().trim(); + String key = conversationPreferenceKey(selectedConversation.getId()); + if (alias.isEmpty() || alias.equals(defaultConversationTitle(selectedConversation))) { + CHAT_PREFERENCES.remove(key); + } else { + CHAT_PREFERENCES.put(key, alias); + } + + lblConversationTitle.setText(getConversationTitle(selectedConversation)); + lvConversations.refresh(); + } + @FXML void btnSendClicked() { if (selectedConversation == null) { @@ -321,10 +354,19 @@ public class ChatController { } private String getConversationTitle(ConversationResponse conversation) { + String alias = CHAT_PREFERENCES.get(conversationPreferenceKey(conversation.getId()), null); + return alias != null && !alias.isBlank() ? alias : defaultConversationTitle(conversation); + } + + private String defaultConversationTitle(ConversationResponse conversation) { String customerLabel = customerLabels.get(conversation.getCustomerId()); return customerLabel != null ? customerLabel : "Customer #" + conversation.getCustomerId(); } + private String conversationPreferenceKey(Long conversationId) { + return "chat.title." + conversationId; + } + private String buildConversationMeta(ConversationResponse conversation) { String assignee; if (conversation.getStaffId() != null) { diff --git a/src/main/resources/org/example/petshopdesktop/main-layout-view.fxml b/src/main/resources/org/example/petshopdesktop/main-layout-view.fxml index e301357f..9daa91e1 100644 --- a/src/main/resources/org/example/petshopdesktop/main-layout-view.fxml +++ b/src/main/resources/org/example/petshopdesktop/main-layout-view.fxml @@ -12,7 +12,7 @@ - + @@ -47,7 +47,7 @@ - + diff --git a/src/main/resources/org/example/petshopdesktop/modelviews/analytics-view.fxml b/src/main/resources/org/example/petshopdesktop/modelviews/analytics-view.fxml index cdf1f90b..dec7a883 100644 --- a/src/main/resources/org/example/petshopdesktop/modelviews/analytics-view.fxml +++ b/src/main/resources/org/example/petshopdesktop/modelviews/analytics-view.fxml @@ -14,7 +14,7 @@ - + @@ -41,7 +41,7 @@ - + diff --git a/src/main/resources/org/example/petshopdesktop/modelviews/chat-view.fxml b/src/main/resources/org/example/petshopdesktop/modelviews/chat-view.fxml index f701a9b5..5ce88160 100644 --- a/src/main/resources/org/example/petshopdesktop/modelviews/chat-view.fxml +++ b/src/main/resources/org/example/petshopdesktop/modelviews/chat-view.fxml @@ -14,7 +14,7 @@ - + @@ -38,7 +38,7 @@ @@ -48,12 +48,12 @@ -