Skip to content

Commit

Permalink
Merge pull request #411 from salemove/feature/MOB-1612_chat_history
Browse files Browse the repository at this point in the history
  • Loading branch information
sm-deployer authored Jan 5, 2023
2 parents c91f63b + f223740 commit 17673e9
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 82 deletions.
1 change: 1 addition & 0 deletions widgetssdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ dependencies {
api "com.glia:android-sdk:$gliaSdkVersion"
// Glia sdk aar
// implementation(name: "glia-core-sdk-$gliaSdkVersion", ext: 'aar')
// api "com.glia:android-sdk:0.26.6-SNAPSHOT" // Used when testing local Core SDK snapshot releases

implementation "com.airbnb.android:lottie:$lottieVersion"
implementation "com.google.code.gson:gson:$gson"
Expand Down
26 changes: 8 additions & 18 deletions widgetssdk/src/main/java/com/glia/widgets/chat/ChatView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -455,19 +455,14 @@ class ChatView(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defSty
item.operatorProfileImgUrl,
isFileDownloaded,
item.isDownloading,
item.operatorId
item.operatorId,
item.messageId,
item.timestamp
)
}
is VisitorAttachmentItem -> {
val isFileDownloaded = FileHelper.isFileDownloaded(item.attachmentFile)
VisitorAttachmentItem(
item.id,
item.viewType,
item.attachmentFile,
isFileDownloaded,
item.isDownloading,
item.showDelivered
)
VisitorAttachmentItem.editDownloadedStatus(item, isFileDownloaded)
}
else -> {
item
Expand Down Expand Up @@ -1020,14 +1015,7 @@ class ChatView(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defSty
): ChatItem {
if (currentChatItem is VisitorAttachmentItem) {
if (currentChatItem.attachmentFile.id == attachmentFile.id) {
return VisitorAttachmentItem(
currentChatItem.id,
currentChatItem.viewType,
currentChatItem.attachmentFile,
isFileExists,
isDownloading,
currentChatItem.showDelivered
)
return VisitorAttachmentItem.editFileStatuses(currentChatItem, isFileExists, isDownloading)
}
} else if (currentChatItem is OperatorAttachmentItem) {
if (currentChatItem.attachmentFile.id == attachmentFile.id) {
Expand All @@ -1039,7 +1027,9 @@ class ChatView(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defSty
currentChatItem.operatorProfileImgUrl,
isFileExists,
isDownloading,
currentChatItem.operatorId
currentChatItem.operatorId,
currentChatItem.messageId,
currentChatItem.timestamp
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import com.glia.widgets.chat.model.history.OperatorChatItem;
import com.glia.widgets.chat.model.history.OperatorMessageItem;
import com.glia.widgets.chat.model.history.OperatorStatusItem;
import com.glia.widgets.chat.model.history.LinkedChatItem;
import com.glia.widgets.chat.model.history.VisitorAttachmentItem;
import com.glia.widgets.chat.model.history.VisitorMessageItem;
import com.glia.widgets.core.dialog.DialogController;
Expand Down Expand Up @@ -93,6 +94,7 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Observable;
Expand Down Expand Up @@ -459,6 +461,10 @@ private void subscribeToMessages() {

private void onMessage(@NonNull ChatMessageInternal messageInternal) {
ChatMessage message = messageInternal.getChatMessage();
if (!isNewMessage(chatState.chatItems, message)) {
return;
}

boolean isUnsentMessage = !chatState.unsentMessages.isEmpty() && chatState.unsentMessages.get(0).getMessage().equals(message.getContent());
Logger.d(TAG, "onMessage: " + message.getContent() + ", id: " + message.getId() + ", isUnsentMessage: " + isUnsentMessage);
if (isUnsentMessage) {
Expand All @@ -469,7 +475,7 @@ private void onMessage(@NonNull ChatMessageInternal messageInternal) {
List<ChatItem> currentChatItems = new ArrayList<>(chatState.chatItems);
int currentMessageIndex = currentChatItems.indexOf(currentMessage);
currentChatItems.remove(currentMessage);
currentChatItems.add(currentMessageIndex, new VisitorMessageItem(message.getId(), false, message.getContent()));
currentChatItems.add(currentMessageIndex, VisitorMessageItem.asNewMessage(message));

// emitting state because no need to change recyclerview items here
emitViewState(chatState
Expand Down Expand Up @@ -518,7 +524,7 @@ private void onSendMessageOperatorOffline(String message) {
private void appendUnsentMessage(String message) {
Logger.d(TAG, "appendUnsentMessage: " + message);
List<VisitorMessageItem> unsentMessages = new ArrayList<>(chatState.unsentMessages);
VisitorMessageItem unsentItem = new VisitorMessageItem(VisitorMessageItem.UNSENT_MESSAGE_ID, false, message);
VisitorMessageItem unsentItem = VisitorMessageItem.asUnsentItem(message);
unsentMessages.add(unsentItem);

List<ChatItem> currentChatItems = new ArrayList<>(chatState.chatItems);
Expand Down Expand Up @@ -890,7 +896,7 @@ private void appendHistoryMessage(List<ChatItem> currentChatItems, ChatMessage m
}

if (message.getContent() != null && !message.getContent().isEmpty()) {
currentChatItems.add(new VisitorMessageItem(VisitorMessageItem.HISTORY_ID, false, message.getContent()));
currentChatItems.add(VisitorMessageItem.asHistoryItem(message));
}
}

Expand Down Expand Up @@ -937,14 +943,8 @@ private void addVisitorAttachmentItemsToChatItems(List<ChatItem> currentChatItem
FilesAttachment filesAttachment = (FilesAttachment) attachment;
AttachmentFile[] files = filesAttachment.getFiles();
for (AttachmentFile file : files) {
int type;
if (file.getContentType().startsWith("image")) {
type = ChatAdapter.VISITOR_IMAGE_VIEW_TYPE;
} else {
type = ChatAdapter.VISITOR_FILE_VIEW_TYPE;
}
currentChatItems.add(
new VisitorAttachmentItem(chatMessage.getId(), type, file, false, false, false)
VisitorAttachmentItem.fromAttachmentFile(chatMessage.getId(), chatMessage.getTimestamp(), file)
);
}
}
Expand All @@ -960,7 +960,7 @@ private void appendSentMessage(List<ChatItem> items, ChatMessage message) {
}

if (message.getContent() != null && !message.getContent().isEmpty()) {
items.add(new VisitorMessageItem(message.getId(), false, message.getContent()));
items.add(VisitorMessageItem.asNewMessage(message));
}
}

Expand Down Expand Up @@ -991,9 +991,9 @@ private void changeDeliveredIndex(List<ChatItem> currentChatItems, VisitorMessag
break;
} else if (!foundDelivered && itemId.equals(messageId)) {
foundDelivered = true;
currentChatItems.set(i, new VisitorMessageItem(itemId, true, item.getMessage()));
currentChatItems.set(i, VisitorMessageItem.editDeliveredStatus(item, true));
} else if (item.isShowDelivered()) {
currentChatItems.set(i, new VisitorMessageItem(itemId, false, item.getMessage()));
currentChatItems.set(i, VisitorMessageItem.editDeliveredStatus(item, false));
}
} else if (currentChatItem instanceof VisitorAttachmentItem) {
VisitorAttachmentItem item = (VisitorAttachmentItem) currentChatItem;
Expand All @@ -1008,17 +1008,7 @@ private void changeDeliveredIndex(List<ChatItem> currentChatItems, VisitorMessag
}

private void setDelivered(List<ChatItem> currentChatItems, int i, VisitorAttachmentItem item, boolean delivered) {
currentChatItems.set(
i,
new VisitorAttachmentItem(
item.getId(),
item.getViewType(),
item.attachmentFile,
item.isFileExists,
item.isDownloading,
delivered
)
);
currentChatItems.set(i, VisitorAttachmentItem.editDeliveredStatus(item, delivered));
}

private void appendOperatorMessage(List<ChatItem> currentChatItems, ChatMessageInternal chatMessageInternal) {
Expand Down Expand Up @@ -1060,7 +1050,8 @@ private void setLastOperatorItemChatHeadVisibility(List<ChatItem> currentChatIte
lastItemInView.singleChoiceOptions,
lastItemInView.selectedChoiceIndex,
lastItemInView.choiceCardImageUrl,
lastItemInView.operatorId
lastItemInView.operatorId,
lastItemInView.getTimestamp()
)
);
} else if (lastItem instanceof OperatorAttachmentItem) {
Expand All @@ -1075,7 +1066,9 @@ private void setLastOperatorItemChatHeadVisibility(List<ChatItem> currentChatIte
lastItemInView.operatorProfileImgUrl,
false,
false,
lastItemInView.operatorId
lastItemInView.operatorId,
lastItemInView.getMessageId(),
lastItemInView.getTimestamp()
)
);
} else if (lastItem instanceof CustomCardItem) {
Expand Down Expand Up @@ -1114,7 +1107,9 @@ private void appendOperatorAttachmentItems(List<ChatItem> currentChatItems, Chat
messageInternal.getOperatorImageUrl().orElse(chatState.operatorProfileImgUrl),
false,
false,
messageInternal.getOperatorId().orElse(UUID.randomUUID().toString())
messageInternal.getOperatorId().orElse(UUID.randomUUID().toString()),
message.getId(),
message.getTimestamp()
)
);
}
Expand All @@ -1128,7 +1123,7 @@ private void appendOperatorOrCustomCardItem(List<ChatItem> currentChatItems, Cha
if (viewType != null) {
appendCustomCardItem(currentChatItems, message, viewType);
} else {
appendOperatorMessageItem(currentChatItems, messageInternal, message);
appendOperatorMessageItem(currentChatItems, messageInternal);
}
}
}
Expand All @@ -1141,24 +1136,15 @@ private void appendCustomCardItem(List<ChatItem> currentChatItems, ChatMessage m
if (customCardShouldShowUseCase.execute(message, customCardType, true)) {
currentChatItems.add(new CustomCardItem(message, viewType));
}

String selectedOptionText = null;
if (message.getAttachment() != null && message.getAttachment() instanceof SingleChoiceAttachment) {
SingleChoiceAttachment singleChoiceAttachment = (SingleChoiceAttachment) message.getAttachment();
if (singleChoiceAttachment != null) {
selectedOptionText = singleChoiceAttachment.getSelectedOptionText();
}
}
if (selectedOptionText != null && !selectedOptionText.isEmpty()) {
currentChatItems.add(
new VisitorMessageItem(VisitorMessageItem.CARD_RESPONSE_ID, false, selectedOptionText)
);
VisitorMessageItem visitorCardResponseItem = VisitorMessageItem.asCardResponseItem(message);
if (visitorCardResponseItem.getMessage() != null && !visitorCardResponseItem.getMessage().isEmpty()) {
currentChatItems.add(visitorCardResponseItem);
}
}

private void appendOperatorMessageItem(List<ChatItem> currentChatItems,
ChatMessageInternal messageInternal,
ChatMessage message) {
ChatMessageInternal messageInternal) {
ChatMessage message = messageInternal.getChatMessage();
MessageAttachment messageAttachment = message.getAttachment();
currentChatItems.add(
new OperatorMessageItem(
Expand All @@ -1170,7 +1156,8 @@ private void appendOperatorMessageItem(List<ChatItem> currentChatItems,
getSingleChoiceAttachmentOptions(messageAttachment),
null,
getSingleChoiceAttachmentImgUrl(messageAttachment),
messageInternal.getOperatorId().orElse(UUID.randomUUID().toString())
messageInternal.getOperatorId().orElse(UUID.randomUUID().toString()),
message.getTimestamp()
)
);
}
Expand Down Expand Up @@ -1277,7 +1264,8 @@ public void singleChoiceOptionClicked(
choiceCardItem.singleChoiceOptions,
optionIndex,
choiceCardItem.choiceCardImageUrl,
choiceCardItem.operatorId
choiceCardItem.operatorId,
choiceCardItem.getTimestamp()
);

List<ChatItem> modifiedItems = new ArrayList<>(chatState.chatItems);
Expand Down Expand Up @@ -1320,7 +1308,7 @@ public void sendCustomCardResponse(String messageId, String text, String value)
}
chatItems.add(
indexForResponseMessage,
new VisitorMessageItem(VisitorMessageItem.CARD_RESPONSE_ID, false, text)
VisitorMessageItem.asUnsentCardResponse(text)
);
emitChatItems(chatState.changeItems(chatItems));
});
Expand Down Expand Up @@ -1377,20 +1365,53 @@ private void loadChatHistory() {
disposable.add(historyDisposable);
}

private void historyLoaded(List<ChatMessageInternal> messages) {
private synchronized void historyLoaded(List<ChatMessageInternal> messages) {
Logger.d(TAG, "historyLoaded");
List<ChatItem> items = new ArrayList<>(chatState.chatItems);
messages = removeDuplicates(items, messages);
if (messages != null && !messages.isEmpty()) {
for (ChatMessageInternal message : messages) {
appendHistoryChatItem(items, message);
}
emitChatItems(chatState.historyLoaded(items));
emitChatItems(chatState.historyLoaded(items.stream().sorted(chatItemComparator).collect(Collectors.toList())));
initGliaEngagementObserving();
} else {
} else if (!chatState.engagementRequested) {
initGliaEngagementObserving();
queueForEngagement();
}
}

private Comparator<ChatItem> chatItemComparator = (chatItem1, chatItem2) -> {
if (chatItem1 instanceof LinkedChatItem && chatItem2 instanceof LinkedChatItem) {
long item1Timestamp = ((LinkedChatItem) chatItem1).getTimestamp();
long item2Timestamp = ((LinkedChatItem) chatItem2).getTimestamp();
if (item1Timestamp < item2Timestamp) {
return -1;
} else if (item1Timestamp > item2Timestamp) {
return 1;
}
}
return 0;
};

private List<ChatMessageInternal> removeDuplicates(List<ChatItem> oldHistory, List<ChatMessageInternal> newHistory) {
if (newHistory == null || newHistory.isEmpty()) {
return newHistory;
}
if (oldHistory == null || oldHistory.isEmpty()) {
return newHistory;
}
return newHistory.stream()
.filter(newMessage -> isNewMessage(oldHistory, newMessage.getChatMessage()))
.collect(Collectors.toList());
}

private boolean isNewMessage(List<ChatItem> oldHistory, ChatMessage newMessage) {
return oldHistory.stream()
.filter(oldMessage -> oldMessage instanceof LinkedChatItem)
.map(oldMessage -> (LinkedChatItem) oldMessage)
.filter(oldMessage -> oldMessage.getMessageId() != null)
.noneMatch(oldMessage -> oldMessage.getMessageId().equals(newMessage.getId()));
}

private void error(Throwable error) {
Expand All @@ -1411,6 +1432,9 @@ public void newEngagementLoaded(OmnicoreEngagement engagement) {
Logger.d(TAG, "unsentMessage sent!");
}
emitViewState(chatState.engagementStarted());
// Loading chat history again on engagement start in case it was an-authenticated visitor that restored ongoing engagement
// Currently there is no direct way to know if Visitor is authenticated.
loadChatHistory();
}

@Override
Expand Down Expand Up @@ -1475,6 +1499,9 @@ public void notificationsDialogDismissed() {

public void queueForEngagementStarted() {
Logger.d(TAG, "queueForEngagementStarted");
if (chatState.isOperatorOnline()) {
return;
}
observeQueueTicketState();
viewInitQueueing();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

import java.util.Objects;

public class CustomCardItem extends ChatItem {
public class CustomCardItem extends LinkedChatItem {
private final ChatMessage message;

public CustomCardItem(ChatMessage message, int viewType) {
super(message.getId(), viewType);
super(message.getId(), viewType, message.getId(), message.getTimestamp());

this.message = message;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.glia.widgets.chat.model.history;

public class LinkedChatItem extends ChatItem {

private final String messageId;
private final long timestamp;

public LinkedChatItem(String id, int viewType, String messageId, long timestamp) {
super(id, viewType);
this.messageId = messageId;
this.timestamp = timestamp;
}

public String getMessageId() {
return messageId;
}

public long getTimestamp() {
return timestamp;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ public OperatorAttachmentItem(
String operatorProfileImgUrl,
boolean isFileExists,
boolean isDownloading,
String operatorId
String operatorId,
String messageId,
long timestamp
) {
super(chatItemId, viewType, showChatHead, operatorProfileImgUrl, operatorId);
super(chatItemId, viewType, showChatHead, operatorProfileImgUrl, operatorId, messageId, timestamp);
this.attachmentFile = attachmentFile;
this.isFileExists = isFileExists;
this.isDownloading = isDownloading;
Expand Down
Loading

0 comments on commit 17673e9

Please sign in to comment.