fix read state tracking
This commit is contained in:
@@ -14,8 +14,10 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.CompletionStage;
|
import java.util.concurrent.CompletionStage;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
@@ -43,6 +45,7 @@ public class ChatRealtimeClient implements WebSocket.Listener {
|
|||||||
private volatile String currentStatus = "Chat disconnected";
|
private volatile String currentStatus = "Chat disconnected";
|
||||||
|
|
||||||
private final Map<Long, ConversationResponse> globalConversations = new HashMap<>();
|
private final Map<Long, ConversationResponse> globalConversations = new HashMap<>();
|
||||||
|
private final Set<Long> readConversationIds = new HashSet<>();
|
||||||
private final List<Consumer<Boolean>> notificationListeners = new ArrayList<>();
|
private final List<Consumer<Boolean>> notificationListeners = new ArrayList<>();
|
||||||
private boolean lastNotificationState = false;
|
private boolean lastNotificationState = false;
|
||||||
|
|
||||||
@@ -79,10 +82,24 @@ public class ChatRealtimeClient implements WebSocket.Listener {
|
|||||||
if (conv != null) {
|
if (conv != null) {
|
||||||
conv.setLastSenderId(senderId);
|
conv.setLastSenderId(senderId);
|
||||||
}
|
}
|
||||||
|
readConversationIds.add(conversationId);
|
||||||
}
|
}
|
||||||
updateNotificationState();
|
updateNotificationState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void markConversationRead(Long conversationId) {
|
||||||
|
synchronized (lock) {
|
||||||
|
readConversationIds.add(conversationId);
|
||||||
|
}
|
||||||
|
updateNotificationState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConversationRead(Long conversationId) {
|
||||||
|
synchronized (lock) {
|
||||||
|
return readConversationIds.contains(conversationId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasActionableChats() {
|
public boolean hasActionableChats() {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
UserSession session = UserSession.getInstance();
|
UserSession session = UserSession.getInstance();
|
||||||
@@ -98,7 +115,8 @@ public class ChatRealtimeClient implements WebSocket.Listener {
|
|||||||
|
|
||||||
// Needs reply (assigned to me and last sender was someone else - customer)
|
// Needs reply (assigned to me and last sender was someone else - customer)
|
||||||
if (currentUserId != null && currentUserId.equals(conv.getStaffId())) {
|
if (currentUserId != null && currentUserId.equals(conv.getStaffId())) {
|
||||||
if (conv.getLastSenderId() != null && !conv.getLastSenderId().equals(currentUserId)) {
|
if (conv.getLastSenderId() != null && !conv.getLastSenderId().equals(currentUserId)
|
||||||
|
&& !readConversationIds.contains(conv.getId())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,6 +320,7 @@ public class ChatRealtimeClient implements WebSocket.Listener {
|
|||||||
conversationsSubscriptionId = null;
|
conversationsSubscriptionId = null;
|
||||||
conversationMessagesSubscriptionId = null;
|
conversationMessagesSubscriptionId = null;
|
||||||
globalConversations.clear();
|
globalConversations.clear();
|
||||||
|
readConversationIds.clear();
|
||||||
updateNotificationState();
|
updateNotificationState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,13 +371,15 @@ public class ChatRealtimeClient implements WebSocket.Listener {
|
|||||||
.notifyNewMessage(message.getSenderDisplayName(), message.getContent());
|
.notifyNewMessage(message.getSenderDisplayName(), message.getContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also update globalConversation last sender if this is the active conversation
|
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
ConversationResponse conv = globalConversations.get(message.getConversationId());
|
ConversationResponse conv = globalConversations.get(message.getConversationId());
|
||||||
if (conv != null) {
|
if (conv != null) {
|
||||||
conv.setLastMessage(message.getContent());
|
conv.setLastMessage(message.getContent());
|
||||||
conv.setLastSenderId(message.getSenderId());
|
conv.setLastSenderId(message.getSenderId());
|
||||||
}
|
}
|
||||||
|
if (message.getSenderId() != null && !message.getSenderId().equals(currentUserId)) {
|
||||||
|
readConversationIds.remove(message.getConversationId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
updateNotificationState();
|
updateNotificationState();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -282,6 +282,8 @@ public class ChatController {
|
|||||||
realtimeClient.subscribeToConversation(newValue.getId());
|
realtimeClient.subscribeToConversation(newValue.getId());
|
||||||
}
|
}
|
||||||
updateChatState(newValue);
|
updateChatState(newValue);
|
||||||
|
realtimeClient.markConversationRead(newValue.getId());
|
||||||
|
refreshSections();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateChatState(ConversationResponse conv) {
|
private void updateChatState(ConversationResponse conv) {
|
||||||
@@ -320,7 +322,8 @@ public class ChatController {
|
|||||||
Long currentUserId = session.getUserId();
|
Long currentUserId = session.getUserId();
|
||||||
boolean needsPickup = item.getHumanRequestedAt() != null && item.getStaffId() == null;
|
boolean needsPickup = item.getHumanRequestedAt() != null && item.getStaffId() == null;
|
||||||
boolean needsReply = currentUserId != null && currentUserId.equals(item.getStaffId())
|
boolean needsReply = currentUserId != null && currentUserId.equals(item.getStaffId())
|
||||||
&& item.getLastSenderId() != null && !item.getLastSenderId().equals(currentUserId);
|
&& item.getLastSenderId() != null && !item.getLastSenderId().equals(currentUserId)
|
||||||
|
&& !ChatRealtimeClient.getInstance().isConversationRead(item.getId());
|
||||||
|
|
||||||
if (needsPickup || needsReply) {
|
if (needsPickup || needsReply) {
|
||||||
title.setStyle("-fx-font-weight: bold; -fx-text-fill: #FF6B6B;");
|
title.setStyle("-fx-font-weight: bold; -fx-text-fill: #FF6B6B;");
|
||||||
@@ -460,6 +463,8 @@ public class ChatController {
|
|||||||
vbMessages.getChildren().add(createMessageBubble(message));
|
vbMessages.getChildren().add(createMessageBubble(message));
|
||||||
if (message.getId() != null) renderedMessageIds.add(message.getId());
|
if (message.getId() != null) renderedMessageIds.add(message.getId());
|
||||||
scrollMessagesToBottom();
|
scrollMessagesToBottom();
|
||||||
|
realtimeClient.markConversationRead(message.getConversationId());
|
||||||
|
refreshSections();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ActivityLogger.getInstance().logException(
|
ActivityLogger.getInstance().logException(
|
||||||
|
|||||||
Reference in New Issue
Block a user