diff --git a/src/components/Chats/CometChatConversationList/ConversationListConfiguration.js b/src/components/Chats/CometChatConversationList/ConversationListConfiguration.js new file mode 100644 index 00000000..1ff4a5d3 --- /dev/null +++ b/src/components/Chats/CometChatConversationList/ConversationListConfiguration.js @@ -0,0 +1,52 @@ +import { ConversationListCustomView } from "../ConversationListCustomView"; +import { ConversationListStyle } from "../"; +import { ConversationListItemConfiguration } from "../../Shared"; + +/** + * @class ConversationListConfiguration + * @param {Number} limit + * @param {String} conversationType + * @param {false} userAndGroupTags + * @param {Array} tags + * @param {Boolean} loadingIconURL + * @param {Object} customView + * @param {false} hideError + * @param {false} enableSoundForMessages + * @param {String} customIncomingMessageSound + * @param {Object} style + * @param {Object} conversationListItemConfiguration + */ +class ConversationListConfiguration { + constructor({ + limit = 30, + conversationType = "both", + userAndGroupTags = false, + tags = [], + loadingIconURL = "", + customView = new ConversationListCustomView({}), + hideError = false, + enableSoundForMessages = false, + customIncomingMessageSound = "", + style = new ConversationListStyle({}), + conversationListItemConfiguration = new ConversationListItemConfiguration( + {} + ), + }) { + this.limit = limit; + this.conversationType = conversationType; + this.userAndGroupTags = userAndGroupTags; + this.tags = tags; + this.loadingIconURL = loadingIconURL; + this.customView = new ConversationListCustomView(customView ?? {}); + this.hideError = hideError; + this.enableSoundForMessages = enableSoundForMessages; + this.customIncomingMessageSound = customIncomingMessageSound; + this.style = new ConversationListStyle(style ?? {}); + this.conversationListItemConfiguration = + new ConversationListItemConfiguration( + conversationListItemConfiguration ?? {} + ); + } +} + +export { ConversationListConfiguration }; diff --git a/src/components/Chats/CometChatConversationList/ConversationListStyle.js b/src/components/Chats/CometChatConversationList/ConversationListStyle.js new file mode 100644 index 00000000..6471d4c2 --- /dev/null +++ b/src/components/Chats/CometChatConversationList/ConversationListStyle.js @@ -0,0 +1,42 @@ +/** + * @class ConversationListStyle + * @description ConversationListStyle class is used for defining the styles for conversation list. + * @param {String} width + * @param {String} height + * @param {String} background + * @param {String} border + * @param {String} borderRadius + * @param {String} loadingIconTint + * @param {String} emptyStateTextFont + * @param {String} emptyStateTextColor + * @param {String} errorStateTextFont + * @param {String} errorStateTextColor + */ + + class ConversationListStyle { + constructor({ + width = "100%", + height = "100%", + background = "", + border = "", + borderRadius = "0", + loadingIconTint = "", + emptyStateTextFont = "", + emptyStateTextColor = "", + errorStateTextFont = "", + errorStateTextColor = "", + }) { + this.width = width; + this.height = height; + this.background = background; + this.border = border; + this.borderRadius = borderRadius; + this.loadingIconTint = loadingIconTint; + this.emptyStateTextFont = emptyStateTextFont; + this.emptyStateTextColor = emptyStateTextColor; + this.errorStateTextFont = errorStateTextFont; + this.errorStateTextColor = errorStateTextColor; + } + } + export { ConversationListStyle }; + \ No newline at end of file diff --git a/src/components/Chats/CometChatConversationList/ConversationListStyles.js b/src/components/Chats/CometChatConversationList/ConversationListStyles.js deleted file mode 100644 index 62aeee9a..00000000 --- a/src/components/Chats/CometChatConversationList/ConversationListStyles.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @class ConversationListStyles - * @description ConversationListStyles class is used for defining the styles for conversation list. - * @param {String} width - * @param {String} height - * @param {String} background - * @param {String} border - * @param {String} borderRadius - * @param {String} loadingIconTint - * @param {String} emptyStateTextFont - * @param {String} emptyStateTextColor - * @param {String} errorStateTextFont - * @param {String} errorStateTextColor - */ - -class ConversationListStyles { - - constructor({ - width = "100%", - height = "100%", - background = "", - border = "", - borderRadius = "0", - loadingIconTint = "", - emptyStateTextFont = "", - emptyStateTextColor = "", - errorStateTextFont = "", - errorStateTextColor = "", - }) { - this.width = width; - this.height = height; - this.background = background; - this.border = border; - this.borderRadius = borderRadius; - this.loadingIconTint = loadingIconTint - this.emptyStateTextFont = emptyStateTextFont; - this.emptyStateTextColor = emptyStateTextColor - this.errorStateTextFont = errorStateTextFont; - this.errorStateTextColor = errorStateTextColor; - } -} -export { ConversationListStyles } \ No newline at end of file diff --git a/src/components/Chats/CometChatConversationList/controller.js b/src/components/Chats/CometChatConversationList/controller.js index 8a87e041..a73f5a3a 100644 --- a/src/components/Chats/CometChatConversationList/controller.js +++ b/src/components/Chats/CometChatConversationList/controller.js @@ -1,167 +1,167 @@ import { CometChat } from "@cometchat-pro/chat"; -import { ConversationTypeConstants } from "../../Shared/Constants/UIKitConstants" +import { ConversationTypeConstants } from "../../Shared/Constants/UIKitConstants"; export class ConversationListManager { - conversationRequest = null; + conversationRequest = null; - conversationListenerId = "chatlist_" + new Date().getTime(); - userListenerId = "chatlist_user_" + new Date().getTime(); - groupListenerId = "chatlist_group_" + new Date().getTime(); - - constructor({ - conversationType = "both", - limit = 30, - tags = [], - userAndGroupTags = false - }) { - switch (conversationType) { - case ConversationTypeConstants[ConversationTypeConstants.users]: - this.conversationRequest = new CometChat.ConversationsRequestBuilder() - .setConversationType(conversationType) - .setLimit(limit) - .withTags(tags.length === 0 ? false : true) - .setTags(tags) - .withUserAndGroupTags(userAndGroupTags) - .build(); + conversationListenerId = "chatlist_" + new Date().getTime(); + userListenerId = "chatlist_user_" + new Date().getTime(); + groupListenerId = "chatlist_group_" + new Date().getTime(); - break; - case ConversationTypeConstants[ConversationTypeConstants.groups]: - this.conversationRequest = new CometChat.ConversationsRequestBuilder() - .setConversationType(conversationType) - .setLimit(limit) - .withTags(tags.length === 0 ? false : true) - .setTags(tags) - .withUserAndGroupTags(userAndGroupTags) - .build(); - break; - default: - this.conversationRequest = new CometChat.ConversationsRequestBuilder() - .setLimit(limit) - .withTags(tags.length === 0 ? false : true) - .setTags(tags) - .withUserAndGroupTags(userAndGroupTags) - .build(); + constructor({ + conversationType = "both", + limit = 30, + tags = [], + userAndGroupTags = false, + }) { + switch (conversationType) { + case ConversationTypeConstants[ConversationTypeConstants.users]: + this.conversationRequest = new CometChat.ConversationsRequestBuilder() + .setConversationType(conversationType) + .setLimit(limit) + .withTags(tags.length === 0 ? false : true) + .setTags(tags) + .withUserAndGroupTags(userAndGroupTags) + .build(); - break; - } - } + break; + case ConversationTypeConstants[ConversationTypeConstants.groups]: + this.conversationRequest = new CometChat.ConversationsRequestBuilder() + .setConversationType(conversationType) + .setLimit(limit) + .withTags(tags.length === 0 ? false : true) + .setTags(tags) + .withUserAndGroupTags(userAndGroupTags) + .build(); + break; + default: + this.conversationRequest = new CometChat.ConversationsRequestBuilder() + .setLimit(limit) + .withTags(tags.length === 0 ? false : true) + .setTags(tags) + .withUserAndGroupTags(userAndGroupTags) + .build(); - fetchNextConversation() { - return this.conversationRequest.fetchNext(); - } + break; + } + } - attachListeners(callback) { - CometChat.addUserListener( - this.userListenerId, - new CometChat.UserListener({ - onUserOnline: (onlineUser) => { - callback("onUserOnline", onlineUser); - }, - onUserOffline: (offlineUser) => { - callback("onUserOffline", offlineUser); - }, - }) - ); + fetchNextConversation() { + return this.conversationRequest.fetchNext(); + } - CometChat.addGroupListener( - this.groupListenerId, - new CometChat.GroupListener({ - onGroupMemberScopeChanged: ( - message, - changedUser, - newScope, - oldScope, - changedGroup - ) => { - callback( - "onGroupMemberScopeChanged", - message, - changedUser, - newScope, - oldScope, - changedGroup - ); - }, - onGroupMemberKicked: (message, kickedUser, kickedBy, kickedFrom) => { - callback( - "onGroupMemberKicked", - message, - kickedUser, - kickedBy, - kickedFrom - ); - }, - onGroupMemberLeft: (message, leavingUser, group) => { - callback("onGroupMemberLeft", message, leavingUser, null, group); - }, - onGroupMemberBanned: (message, bannedUser, bannedBy, bannedFrom) => { - callback( - "onGroupMemberBanned", - message, - bannedUser, - bannedBy, - bannedFrom - ); - }, - onMemberAddedToGroup: ( - message, - userAdded, - userAddedBy, - userAddedIn - ) => { - callback( - "onMemberAddedToGroup", - message, - userAdded, - userAddedBy, - userAddedIn - ); - }, - onGroupMemberJoined: (message, joinedUser, joinedGroup) => { - callback( - "onGroupMemberJoined", - message, - joinedUser, - null, - joinedGroup - ); - }, - }) - ); + attachListeners(callback) { + CometChat.addUserListener( + this.userListenerId, + new CometChat.UserListener({ + onUserOnline: (onlineUser) => { + callback("onUserOnline", onlineUser); + }, + onUserOffline: (offlineUser) => { + callback("onUserOffline", offlineUser); + }, + }) + ); - CometChat.addMessageListener( - this.conversationListenerId, - new CometChat.MessageListener({ - onTextMessageReceived: (textMessage) => { - callback("onTextMessageReceived", textMessage); - }, - onMediaMessageReceived: (mediaMessage) => { - callback("onMediaMessageReceived", mediaMessage); - }, - onCustomMessageReceived: (customMessage) => { - callback("onCustomMessageReceived", customMessage); - }, - onMessageDeleted: (deletedMessage) => { - callback("onMessageDeleted", deletedMessage); - }, - onMessageEdited: (editedMessage) => { - callback("onMessageEdited", editedMessage); - }, - onMessagesRead: (messageReceipt) => { - callback("onMessagesRead", messageReceipt); - }, - onTypingStarted: (typingIndicator) => { - callback("onTypingStarted", typingIndicator, true); - }, - onTypingEnded: (typingIndicator) => { - callback("onTypingEnded", typingIndicator, false); - }, - }) - ); - } - removeListeners() { - CometChat.removeMessageListener(this.conversationListenerId); - CometChat.removeUserListener(this.userListenerId); - CometChat.removeGroupListener(this.groupListenerId); - } + CometChat.addGroupListener( + this.groupListenerId, + new CometChat.GroupListener({ + onGroupMemberScopeChanged: ( + message, + changedUser, + newScope, + oldScope, + changedGroup + ) => { + callback( + "onGroupMemberScopeChanged", + message, + changedUser, + newScope, + oldScope, + changedGroup + ); + }, + onGroupMemberKicked: (message, kickedUser, kickedBy, kickedFrom) => { + callback( + "onGroupMemberKicked", + message, + kickedUser, + kickedBy, + kickedFrom + ); + }, + onGroupMemberLeft: (message, leavingUser, group) => { + callback("onGroupMemberLeft", message, leavingUser, null, group); + }, + onGroupMemberBanned: (message, bannedUser, bannedBy, bannedFrom) => { + callback( + "onGroupMemberBanned", + message, + bannedUser, + bannedBy, + bannedFrom + ); + }, + onMemberAddedToGroup: ( + message, + userAdded, + userAddedBy, + userAddedIn + ) => { + callback( + "onMemberAddedToGroup", + message, + userAdded, + userAddedBy, + userAddedIn + ); + }, + onGroupMemberJoined: (message, joinedUser, joinedGroup) => { + callback( + "onGroupMemberJoined", + message, + joinedUser, + null, + joinedGroup + ); + }, + }) + ); + + CometChat.addMessageListener( + this.conversationListenerId, + new CometChat.MessageListener({ + onTextMessageReceived: (textMessage) => { + callback("onTextMessageReceived", textMessage); + }, + onMediaMessageReceived: (mediaMessage) => { + callback("onMediaMessageReceived", mediaMessage); + }, + onCustomMessageReceived: (customMessage) => { + callback("onCustomMessageReceived", customMessage); + }, + onMessageDeleted: (deletedMessage) => { + callback("onMessageDeleted", deletedMessage); + }, + onMessageEdited: (editedMessage) => { + callback("onMessageEdited", editedMessage); + }, + onMessagesRead: (messageReceipt) => { + callback("onMessagesRead", messageReceipt); + }, + onTypingStarted: (typingIndicator) => { + callback("onTypingStarted", typingIndicator, true); + }, + onTypingEnded: (typingIndicator) => { + callback("onTypingEnded", typingIndicator, false); + }, + }) + ); + } + removeListeners() { + CometChat.removeMessageListener(this.conversationListenerId); + CometChat.removeUserListener(this.userListenerId); + CometChat.removeGroupListener(this.groupListenerId); + } } diff --git a/src/components/Chats/CometChatConversationList/hooks.js b/src/components/Chats/CometChatConversationList/hooks.js index 74eb59c4..e5f2dd55 100644 --- a/src/components/Chats/CometChatConversationList/hooks.js +++ b/src/components/Chats/CometChatConversationList/hooks.js @@ -4,70 +4,48 @@ import { ConversationListManager } from "./controller"; import { CometChatConversationEvents } from "../CometChatConversationEvents"; export const Hooks = ( - conversationType, - limit, - tags, - userAndGroupTags, - setConversationList, - conversationCallback, - conversationListManager, - handlers, - callbackData, - loggedInUser, - handleConversations, - confirmDelete + conversationType, + limit, + tags, + userAndGroupTags, + setConversationList, + conversationCallback, + conversationListManager, + loggedInUser, + handleConversations, ) => { - useEffect(() => { - CometChat.getLoggedinUser() - .then((user) => { - loggedInUser.current = { ...user }; - }) - .catch((error) => { - CometChatConversationEvents.emit( - CometChatConversationEvents.onError, - error - ); - }); + useEffect(() => { + CometChat.getLoggedinUser() + .then((user) => { + loggedInUser.current = { ...user }; + }) + .catch((error) => { + CometChatConversationEvents.emit( + CometChatConversationEvents.onError, + error + ); + }); + }, []); - }, []); + useEffect(() => { + try { + conversationListManager.current = new ConversationListManager({ + conversationType: conversationType, + limit: limit, + tags: tags, + userAndGroupTags: userAndGroupTags, + }); + conversationListManager.current?.attachListeners(conversationCallback); + setConversationList([]); + handleConversations(); - useEffect(() => { - try { - conversationListManager.current = new ConversationListManager({ - conversationType: conversationType, - limit: limit, - tags: tags, - userAndGroupTags: userAndGroupTags - }); - conversationListManager.current?.attachListeners(conversationCallback); - setConversationList([]); - handleConversations(); - - return () => { - if (conversationListManager?.current?.removeListeners) { - conversationListManager.current.removeListeners(); - } - }; - } catch (e) { - CometChatConversationEvents.emit( - CometChatConversationEvents.onError, - e - ); - } - }, [ - conversationType, - limit, - tags?.length, - userAndGroupTags - ]); - - useEffect(() => { - try { - const handler = handlers[callbackData?.name]; - - if (handler) return handler(...callbackData?.args); - } catch (e) { - throw (e) - } - }, [callbackData]); + return () => { + if (conversationListManager?.current?.removeListeners) { + conversationListManager.current.removeListeners(); + } + }; + } catch (e) { + CometChatConversationEvents.emit(CometChatConversationEvents.onError, e); + } + }, [conversationType, limit, tags?.length, userAndGroupTags]); }; diff --git a/src/components/Chats/CometChatConversationList/index.js b/src/components/Chats/CometChatConversationList/index.js index 060c54ae..34a12d6e 100644 --- a/src/components/Chats/CometChatConversationList/index.js +++ b/src/components/Chats/CometChatConversationList/index.js @@ -6,21 +6,24 @@ import { Hooks } from "./hooks"; import * as styles from "./style"; import loadingIcon from "./resources/spinner.svg"; import { - CometChatSoundManager, - CometChatConversationListItem, - localize, - CometChatTheme, - ReceiverTypeConstants, - MessageCategoryConstants, - ConversationTypeConstants, - CometChatBackdrop, - CometChatConfirmDialog, - ConversationListItemConfiguration, - ConversationOptionConstants, - ConversationListItemStyles, + CometChatSoundManager, + CometChatConversationListItem, + localize, + CometChatTheme, + ReceiverTypeConstants, + MessageCategoryConstants, + ConversationTypeConstants, + CometChatBackdrop, + CometChatConfirmDialog, + ConversationListItemConfiguration, + ConversationOptionConstants, + ConversationListItemStyle, } from "../../Shared"; import { CometChatConversationEvents } from "../"; -import { ConversationListStyles, CometChatConversationOptions } from "../../Chats"; +import { + ConversationListStyles, + CometChatConversationOptions, +} from "../../Chats"; import { ConversationListCustomView } from "../ConversationListCustomView"; import deleteIcon from "./resources/delete.svg"; @@ -33,1047 +36,1199 @@ import deleteIcon from "./resources/delete.svg"; * */ const ConversationList = React.forwardRef((props, ref) => { + /** + * Props destructuring + */ + const { + activeConversation, + emptyText, + errorText, + conversationType, + limit, + hideError, + tags, + userAndGroupTags, + loadingIconURL, + style, + enableSoundForMessages, + customIncomingMessageSound, + customView, + conversationListItemConfiguration, + theme, + } = props; + + /** + * Component internal state + */ + const loggedInUser = useRef(null); + const conversationListManager = useRef( + new ConversationListManager({ + conversationType: conversationType, + limit: limit, + tags: tags, + userAndGroupTags: userAndGroupTags, + }) + ); + const [conversationList, setConversationList] = useState([]); + const [message, setMessage] = useState(localize("LOADING")); + const [showConfirm, setShowConfirm] = useState({ + show: false, + message: localize("CONFIRM_DELETE_CONVERSATION"), + confirmButtonText: localize("DELETE"), + conversation: null, + onCancel: () => {}, + }); + const activeConversationRef = React.useRef(null); + const callbackDataRef = React.useRef(null); + + /** + * Component private scoping + */ + const _conversationListItemConfiguration = + new ConversationListItemConfiguration( + conversationListItemConfiguration ?? {} + ); + const _theme = new CometChatTheme(theme ?? {}); + activeConversationRef.current = activeConversation; + + /** + * Component internal handlers/methods + */ + + const conversationCallback = (listenerName, ...args) => { + callbackDataRef.current = { name: listenerName, args: [...args] }; + try { + const handler = handlers[callbackDataRef.current?.name]; + + if (handler) return handler(...callbackDataRef.current?.args); + } catch (e) { + throw e; + } + }; + + /** + * Mark the incoming message as delivered + */ + const markMessageAsDelivered = (message) => { + if (message.hasOwnProperty("deliveredAt") === false) { + CometChat.markAsDelivered(message); + } + }; + + /** + * + * If the incoming message is 1-1 conversation, and the conversation type filter is set to groups return false + * If the incoming message is group conversation, and the conversation type filter is set to users return false + * else return true + * + */ + React.useImperativeHandle(ref, () => ({ + resetUnreadCount: resetUnreadCount, + updateLastMessage: updateLastMessage, + updateConversationonEditOrDeleteMessage: + updateConversationonEditOrDeleteMessage, + removeConversation: removeConversation, + deleteConversation: deleteConversation, + updateConversation: updateConversation, + })); + + const filterByConversationType = (message) => { + if (conversationType !== ConversationTypeConstants.both) { + if ( + (conversationType === ConversationTypeConstants.users && + message?.receiverType === ReceiverTypeConstants.group) || + (conversationType === ConversationTypeConstants.groups && + message?.receiverType === ReceiverTypeConstants.user) + ) { + return false; + } + } + return true; + }; + + /** + * + * Converting message object received in the listener callback to conversation object + */ + const getConversationFromMessage = (message) => { + return new Promise((resolve, reject) => { + CometChat.CometChatHelper.getConversationFromMessage(message) + .then((conversation) => { + let conversationKey = conversationList.findIndex( + (c) => c.conversationId === conversation.conversationId + ); + if (conversationKey > -1) { + resolve({ + conversationKey: conversationKey, + conversationId: conversation.conversationId, + conversationType: conversation.conversationType, + conversationWith: conversation.conversationWith, + conversation: conversationList[conversationKey], + conversations: [...conversationList], + }); + } + resolve({ + conversationKey: conversationKey, + conversationId: conversation.conversationId, + conversationType: conversation.conversationType, + conversationWith: conversation.conversationWith, + conversation: conversation, + conversations: [...conversationList], + }); + }) + .catch((error) => { + CometChatConversationEvents.emit( + CometChatConversationEvents.onError, + error + ); + reject(error); + }); + }); + }; + + const getUnreadMessageCount = ( + message, + conversation = {}, + activeConversation = null + ) => { + let unreadMessageCount = conversation?.unreadMessageCount + ? Number(conversation?.unreadMessageCount) + : 0; + + unreadMessageCount = shouldIncrementCount(message) + ? ++unreadMessageCount + : unreadMessageCount; + + unreadMessageCount = + activeConversationRef.current?.conversationId === + conversation?.conversationId + ? 0 + : unreadMessageCount; + + return unreadMessageCount; + }; + + /** + * + * If the message is sent by the logged in user, return false + * If the message has category message or has incrementUnreadCount key in the metadata with value set to true, return true else return false + * + */ + const shouldIncrementCount = (message) => { + if (message?.sender?.uid === loggedInUser?.current?.uid) { + return false; + } + + if ( + message?.category === MessageCategoryConstants.message || + message?.metadata?.incrementUnreadCount === true + ) { + return true; + } + return false; + }; + + /** + * play notification sound for incoming messages + */ + const playNotificationSound = (message) => { /** - * Props destructuring + * If unreadcount is not incremented, don't play notification sound */ - const { - activeConversation, - emptyText, - errorText, - - conversationType, - limit, - hideError, - tags, - userAndGroupTags, - loadingIconURL, - style, - enableSoundForMessages, - customIncomingMessageSound, - customView, - conversationListItemConfiguration, - theme - } = props; - + if (!shouldIncrementCount(message)) { + return false; + } /** - * Component internal state - */ - const loggedInUser = useRef(null); - const conversationListManager = useRef( - new ConversationListManager({ - conversationType: conversationType, - limit: limit, - tags: tags, - userAndGroupTags: userAndGroupTags - }) + * If customIncomingMessageSound url is present then CometChatSoundManager will play this sound + else play the default sound + */ + if ( + enableSoundForMessages && + activeConversation?.conversationType && + activeConversation?.conversationWith + ) { + const receiverType = message.getReceiverType(); + const receiverId = + receiverType === ReceiverTypeConstants.user + ? message?.getSender()?.getUid() + : message?.getReceiverId(); + + if ( + receiverId !== activeConversation?.conversationWith?.uid && + receiverId !== activeConversation?.conversationWith?.guid + ) { + if (customIncomingMessageSound) { + CometChatSoundManager.play(customIncomingMessageSound); + } else { + CometChatSoundManager.play( + CometChatSoundManager.Sound.incomingMessageFromOther + ); + } + } + } + }; + + /** + * + * When a user goes online/ offline + */ + const handleUsers = (user) => { + const conversationKey = conversationList.findIndex( + (eachConversation) => + eachConversation.conversationType && + eachConversation.conversationType === ReceiverTypeConstants.user && + eachConversation.conversationWith && + eachConversation.conversationWith.uid && + eachConversation.conversationWith.uid === user.uid ); - const [conversationList, setConversationList] = useState([]); - const [callbackData, setCallbackData] = useState(null); - const [message, setMessage] = useState(localize("LOADING")); - const [showConfirm, setShowConfirm] = useState({ - show: false, - message: localize("CONFIRM_DELETE_CONVERSATION"), - confirmButtonText: localize("DELETE"), - conversation: null, - onCancel: () => { }, - }) + if (conversationKey > -1) { + let conversations = [...conversationList]; + let conversation = conversations[conversationKey]; + let conversationWith = { + ...conversation.conversationWith, + status: user.getStatus(), + }; + + let newConversation = { + ...conversation, + conversationWith: conversationWith, + }; + conversations.splice(conversationKey, 1, newConversation); + setConversationList(conversations); + } + }; + + /** + * + * When a text message / media message / custom message is received + */ + const handleMessages = (...options) => { + const message = options[0]; /** - * Component private scoping + * marking the incoming messages as read */ - const _conversationListItemConfiguration = new ConversationListItemConfiguration(conversationListItemConfiguration ?? {}); - const _theme = new CometChatTheme(theme ?? {}); - - + markMessageAsDelivered(message); /** - * Component internal handlers/methods + * If the incoming message is 1-1 and the conversation type filter is set to group, return false + * OR + * If the incoming message is group and the conversation type filter is set to "users", return false + * ELSE + * return true */ + if (filterByConversationType() === false) { + return false; + } + CometChat.CometChatHelper.getConversationFromMessage(message) + .then((conversation) => { + setConversationList((prevConversationList) => { + const list = [...prevConversationList]; + + let conversationKey = prevConversationList.findIndex( + (c) => c.conversationId === conversation.conversationId + ); + // const lastMessage = { ...conversation?.lastMessage, ...message, data: {...message.data} }; - const conversationCallback = (listenerName, ...args) => { - setCallbackData({ name: listenerName, args: [...args] }); - }; + if (conversationKey > -1) { + const latestConversation = prevConversationList[conversationKey]; - /** - * Mark the incoming message as delivered - */ - const markMessageAsDelivered = (message) => { - if (message.hasOwnProperty("deliveredAt") === false) { - CometChat.markAsDelivered(message); - } - }; + const lastMessage = { + ...latestConversation?.lastMessage, + ...message, + data: { ...message.data }, + }; + const unreadMessageCount = getUnreadMessageCount( + message, + latestConversation + ); - /** - * - * If the incoming message is 1-1 conversation, and the conversation type filter is set to groups return false - * If the incoming message is group conversation, and the conversation type filter is set to users return false - * else return true - * - */ - React.useImperativeHandle(ref, () => ({ - resetUnreadCount: resetUnreadCount, - updateLastMessage: updateLastMessage, - removeConversation: removeConversation, - deleteConversation: deleteConversation, - updateConversation: updateConversation - })); - - const filterByConversationType = (message) => { - if (conversationType !== ConversationTypeConstants.both) { - if ( - (conversationType === ConversationTypeConstants.users && - message?.receiverType === ReceiverTypeConstants.group) || - (conversationType === ConversationTypeConstants.groups && - message?.receiverType === ReceiverTypeConstants.user) - ) { - return false; - } - } - return true; - }; + const newConversation = { + ...latestConversation, + conversationId: latestConversation.conversationId, + conversationType: latestConversation.conversationType, + conversationWith: { ...latestConversation.conversationWith }, + unreadMessageCount: unreadMessageCount, + lastMessage: { ...lastMessage }, + }; - /** - * - * Converting message object received in the listener callback to conversation object - */ - const getConversationFromMessage = (message) => { - return new Promise((resolve, reject) => { - CometChat.CometChatHelper.getConversationFromMessage(message) - .then((conversation) => { - let conversationKey = conversationList.findIndex( - (c) => c.conversationId === conversation.conversationId - ); - - if (conversationKey > -1) { - resolve({ - conversationKey: conversationKey, - conversationId: conversation.conversationId, - conversationType: conversation.conversationType, - conversationWith: conversation.conversationWith, - conversation: conversationList[conversationKey], - conversations: [...conversationList], - }); - } - - resolve({ - conversationKey: conversationKey, - conversationId: conversation.conversationId, - conversationType: conversation.conversationType, - conversationWith: conversation.conversationWith, - conversation: conversation, - conversations: [...conversationList], - }); - }) - .catch((error) => { - CometChatConversationEvents.emit( - CometChatConversationEvents.onError, - error - ); - reject(error) - }); - }); - }; + //play notification sound + playNotificationSound(message); - const getUnreadMessageCount = (message, conversation = {}) => { - let unreadMessageCount = conversation?.unreadMessageCount ? Number(conversation?.unreadMessageCount) : 0; + list.splice(conversationKey, 1); + list.unshift(newConversation); - unreadMessageCount = shouldIncrementCount(message) ? ++unreadMessageCount : unreadMessageCount; + return [...list]; + } else { + const lastMessage = { + ...conversation?.lastMessage, + ...message, + data: { ...message.data }, + }; + const unreadMessageCount = getUnreadMessageCount( + message, + conversation + ); - return unreadMessageCount; - }; + const newConversation = new CometChat.Conversation( + conversation.conversationId, + conversation.conversationType, + lastMessage, + conversation.conversationWith, + unreadMessageCount + ); - /** - * - * If the message is sent by the logged in user, return false - * If the message has category message or has incrementUnreadCount key in the metadata with value set to true, return true else return false - * - */ - const shouldIncrementCount = (message) => { - if (message?.sender?.uid === loggedInUser?.current?.uid) { - return false; - } + list.unshift(newConversation); - if ( - message?.category === MessageCategoryConstants.message || (message?.metadata?.incrementUnreadCount === true) - ) { - return true; + return [...list]; + } + }); + }) + .catch((error) => + CometChatConversationEvents.emit( + CometChatConversationEvents.onError, + error + ) + ); + }; + + /** + * Listener callback when a message is edited, deleted or updated + */ + const handleMessageActions = (...options) => { + const message = options[0]; + + getConversationFromMessage(message).then((response) => { + setConversationList( + (prevConversationList) => { + const conversations = [...prevConversationList]; + let conversationKey = prevConversationList.findIndex( + (c) => c.conversationId === response.conversation.conversationId + ); + + const latestConversation = prevConversationList[conversationKey]; + if ( + conversationKey > -1 && + latestConversation?.lastMessage?.id === message?.id + ) { + const lastMessage = { + ...latestConversation?.lastMessage, + ...message, + data: { ...message.data }, + }; + const unreadMessageCount = getUnreadMessageCount( + message, + latestConversation + ); + const newConversation = new CometChat.Conversation( + latestConversation.conversationId, + latestConversation.conversationType, + lastMessage, + response.conversationWith, + unreadMessageCount, + latestConversation + ); + conversations.splice(conversationKey, 1, newConversation); + return [...conversations]; + } else { + return [...prevConversationList]; + } } - return false; - }; + // } else { + // const { + // conversationId, + // conversationType, + // conversationWith, + // conversation, + // conversations, + // } = response; + // const lastMessage = { + // ...conversation.lastMessage, ...message, data: { + // ...message.data + // } }; + // const unreadMessageCount = getUnreadMessageCount(message, conversation); + // if (lastMessage.id === message.id) { + // const newConversation = new CometChat.Conversation( + // conversationId, + // conversationType, + // lastMessage, + // conversationWith, + // unreadMessageCount + // ) + // conversations.unshift(newConversation); + // return [...conversations] + // } + // } + ); + }); + }; + + /** + * + * Listener callback when a message is read + */ + const handleMessageReadActions = (...options) => { + const messageReceipt = options[0]; + + let conversationKey = conversationList.findIndex( + (conversation) => + messageReceipt?.receiverType === conversation?.conversationType && + (messageReceipt?.receiver === conversation?.conversationWith?.uid || + messageReceipt?.receiver === conversation?.conversationWith?.guid) + ); - /** - * play notification sound for incoming messages - */ - const playNotificationSound = (message) => { + if (conversationKey > -1) { + const conversations = { ...conversationList }; + const conversation = conversations[conversationKey]; + let unreadMessageCount = getUnreadMessageCount(message, conversation); + + /** + * If the message id in the read receipt is greater than or equal to the lastmessage id, set unreadmessagecount to 0 + */ + if (messageReceipt?.messageId >= conversation?.lastMessage?.id) { + unreadMessageCount = 0; + } + + const newConversation = new CometChat.Conversation( + conversation.conversationId, + conversation.conversationType, + conversation.lastMessage, + conversation.conversationWith, + unreadMessageCount + ); + + conversations.splice(conversationKey, 1, newConversation); + setConversationList(conversations); + } + }; + + /** + * + * Listener callback when a user joins/added to the group + */ + const handleGroupMemberAddition = (...options) => { + const message = options[0]; + const newUser = options[1]; + const group = options[3]; + + getConversationFromMessage(message).then((response) => { + const { + conversationKey, + conversationId, + conversationType, + conversationWith, + conversation, + conversations, + } = response; + + if (conversationKey > -1) { + const lastMessage = { ...conversation.lastMessage, ...message }; + const newConversationWith = { ...conversationWith, ...group }; + const unreadMessageCount = getUnreadMessageCount(message, conversation); + + const newConversation = new CometChat.Conversation( + conversationId, + conversationType, + lastMessage, + newConversationWith, + unreadMessageCount + ); + conversations.splice(conversationKey, 1, newConversation); + setConversationList(conversations); + } else if (loggedInUser?.current?.uid === newUser.uid) { /** - * If unreadcount is not incremented, don't play notification sound + * If the loggedin user is added to the group, add the conversation to the chats list */ - if (!shouldIncrementCount(message)) { - return false; - } - /** - * If customIncomingMessageSound url is present then CometChatSoundManager will play this sound - else play the default sound - */ - if ( - enableSoundForMessages && - activeConversation?.conversationType && - activeConversation?.conversationWith - ) { - const receiverType = message.getReceiverType(); - const receiverId = receiverType === ReceiverTypeConstants.user ? message?.getSender()?.getUid() : message?.getReceiverId(); - - if ( - receiverId !== activeConversation?.conversationWith?.uid && - receiverId !== activeConversation?.conversationWith?.guid - ) { - if (customIncomingMessageSound) { - CometChatSoundManager.play(customIncomingMessageSound); - } else { - CometChatSoundManager.play( - CometChatSoundManager.Sound.incomingMessageFromOther - ); - } - } - } - }; - - /** - * - * When a user goes online/ offline - */ - const handleUsers = (user) => { - const conversationKey = conversationList.findIndex( - (eachConversation) => - eachConversation.conversationType && - eachConversation.conversationType === ReceiverTypeConstants.user && - eachConversation.conversationWith && - eachConversation.conversationWith.uid && - eachConversation.conversationWith.uid === user.uid + const lastMessage = { ...message }; + const newConversationWith = { + ...conversationWith, + ...group, + hasJoined: true, + }; + const unreadMessageCount = getUnreadMessageCount(message, conversation); + + const newConversation = new CometChat.Conversation( + conversationId, + conversationType, + lastMessage, + newConversationWith, + unreadMessageCount ); - if (conversationKey > -1) { - let conversations = [...conversationList]; - let conversation = conversations[conversationKey]; - let conversationWith = { - ...conversation.conversationWith, - status: user.getStatus(), - }; - - let newConversation = { - ...conversation, - conversationWith: conversationWith, - }; - conversations.splice(conversationKey, 1, newConversation); - setConversationList(conversations); - } - }; + conversations.unshift(newConversation); + setConversationList(conversations); + } + }); + }; + + /** + * + * Listener callback when a member is kicked from / has left the group + */ + const handleGroupMemberRemoval = (...options) => { + const message = options[0]; + const removedUser = options[1]; + const group = options[3]; + + getConversationFromMessage(message).then((response) => { + const { + conversationKey, + conversationId, + conversationType, + conversationWith, + conversation, + conversations, + } = response; - /** - * - * When a text message / media message / custom message is received - */ - const handleMessages = (...options) => { - const message = options[0]; + if (conversationKey > -1) { /** - * marking the incoming messages as read + * If the loggedin user is removed from the group, remove the conversation from the chats list */ - markMessageAsDelivered(message); + if (loggedInUser?.current?.uid === removedUser.uid) { + conversations.splice(conversationKey, 1); + setConversationList(conversations); + } else { + const lastMessage = { ...conversation.lastMessage, ...message }; + const newConversationWith = { ...conversationWith, ...group }; + const unreadMessageCount = getUnreadMessageCount( + message, + conversation + ); + + const newConversation = new CometChat.Conversation( + conversationId, + conversationType, + lastMessage, + newConversationWith, + unreadMessageCount + ); + + conversations.splice(conversationKey, 1, newConversation); + setConversationList(conversations); + } + } + }); + }; + + /** + * + * Listener callback when a member is banned from the group + */ + const handleGroupMemberBan = (...options) => { + const message = options[0]; + const removedUser = options[1]; + const group = options[3]; + + getConversationFromMessage(message).then((response) => { + const { + conversationKey, + conversationId, + conversationType, + conversationWith, + conversation, + conversations, + } = response; + + if (conversationKey > -1) { /** - * If the incoming message is 1-1 and the conversation type filter is set to group, return false - * OR - * If the incoming message is group and the conversation type filter is set to "users", return false - * ELSE - * return true + * If the loggedin user is banned from the group, remove the conversation from the chats list */ - if (filterByConversationType() === false) { - return false; + if (loggedInUser?.current?.uid === removedUser.uid) { + conversations.splice(conversationKey, 1); + setConversationList(conversations); + } else { + const lastMessage = { ...conversation.lastMessage, ...message }; + const newConversationWith = { ...conversationWith, ...group }; + const unreadMessageCount = getUnreadMessageCount( + message, + conversation + ); + + const newConversation = new CometChat.Conversation( + conversationId, + conversationType, + lastMessage, + newConversationWith, + unreadMessageCount + ); + + conversations.splice(conversationKey, 1, newConversation); + setConversationList(conversations); } - - getConversationFromMessage(message).then((response) => { - const { - conversationKey, - conversationId, - conversationType, - conversationWith, - conversation, - conversations, - } = response; - - const lastMessage = { ...conversation?.lastMessage, ...message }; - - if (conversationKey > -1) { - const unreadMessageCount = getUnreadMessageCount(message, conversation); - - const newConversation = new CometChat.Conversation( - conversationId, - conversationType, - lastMessage, - conversationWith, - unreadMessageCount - ); - conversations.splice(conversationKey, 1); - conversations.unshift(newConversation); - setConversationList(conversations); - - //play notification sound - playNotificationSound(message); - } else { - const unreadMessageCount = getUnreadMessageCount(message); - const newConversation = new CometChat.Conversation( - conversationId, - conversationType, - lastMessage, - conversationWith, - unreadMessageCount - ); - conversations.unshift(newConversation); - setConversationList(conversations); - - //play notification sound - playNotificationSound(message); - } - }); - }; - - /** - * Listener callback when a message is edited, deleted or updated - */ - const handleMessageActions = (...options) => { - const message = options[0]; - - getConversationFromMessage(message).then((response) => { - const { - conversationKey, - conversationId, - conversationType, - conversationWith, - conversation, - conversations, - } = response; - - if (conversationKey > -1 && conversation.lastMessage.id === message.id) { - const lastMessage = { ...conversation.lastMessage, ...message }; - const unreadMessageCount = getUnreadMessageCount(message, conversation); - - const newConversation = new CometChat.Conversation( - conversationId, - conversationType, - lastMessage, - conversationWith, - unreadMessageCount - ); - conversations.splice(conversationKey, 1, newConversation); - setConversationList(conversations); - } - }); - }; - - /** - * - * Listener callback when a message is read - */ - const handleMessageReadActions = (...options) => { - const messageReceipt = options[0]; - - let conversationKey = conversationList.findIndex( - (conversation) => - messageReceipt?.receiverType === conversation?.conversationType && - (messageReceipt?.receiver === conversation?.conversationWith?.uid || - messageReceipt?.receiver === conversation?.conversationWith?.guid) - ); - - if (conversationKey > -1) { - const conversations = { ...conversationList }; - const conversation = conversations[conversationKey]; - let unreadMessageCount = getUnreadMessageCount(message, conversation); - - /** - * If the message id in the read receipt is greater than or equal to the lastmessage id, set unreadmessagecount to 0 - */ - if (messageReceipt?.messageId >= conversation?.lastMessage?.id) { - unreadMessageCount = 0; - } - - const newConversation = new CometChat.Conversation( - conversation.conversationId, - conversation.conversationType, - conversation.lastMessage, - conversation.conversationWith, - unreadMessageCount - ); - - conversations.splice(conversationKey, 1, newConversation); - setConversationList(conversations); + } + }); + }; + + /** + * + * Listener callback when a group member scope is updated + */ + const handleGroupMemberScopeChange = (...options) => { + const message = options[0]; + const user = options[1]; + const newScope = options[2]; + const group = options[4]; + + getConversationFromMessage(message).then((response) => { + const { + conversationKey, + conversationId, + conversationType, + conversationWith, + conversation, + conversations, + } = response; + + if (conversationKey > -1) { + const lastMessage = { ...conversation.lastMessage, ...message }; + const unreadMessageCount = getUnreadMessageCount(message, conversation); + + if (loggedInUser?.current?.uid === user.uid) { + const newConversationWith = { + ...conversationWith, + ...group, + scope: newScope, + }; + + const newConversation = new CometChat.Conversation( + conversationId, + conversationType, + lastMessage, + newConversationWith, + unreadMessageCount + ); + + conversations.splice(conversationKey, 1); + conversations.unshift(newConversation); + setConversationList(conversations); + } else { + let newConversationWith = { ...conversationWith, ...group }; + + const newConversation = new CometChat.Conversation( + conversationId, + conversationType, + lastMessage, + newConversationWith, + unreadMessageCount + ); + + conversations.splice(conversationKey, 1, newConversation); + setConversationList(conversations); } - }; - - /** - * - * Listener callback when a user joins/added to the group - */ - const handleGroupMemberAddition = (...options) => { - const message = options[0]; - const newUser = options[1]; - const group = options[3]; - - getConversationFromMessage(message).then((response) => { - const { - conversationKey, - conversationId, - conversationType, - conversationWith, - conversation, - conversations, - } = response; - - if (conversationKey > -1) { - const lastMessage = { ...conversation.lastMessage, ...message }; - const newConversationWith = { ...conversationWith, ...group }; - const unreadMessageCount = getUnreadMessageCount(message, conversation); - - const newConversation = new CometChat.Conversation( - conversationId, - conversationType, - lastMessage, - newConversationWith, - unreadMessageCount - ); - conversations.splice(conversationKey, 1, newConversation); - setConversationList(conversations); - } else if (loggedInUser?.current?.uid === newUser.uid) { - /** - * If the loggedin user is added to the group, add the conversation to the chats list - */ - const lastMessage = { ...message }; - const newConversationWith = { - ...conversationWith, - ...group, - hasJoined: true, - }; - const unreadMessageCount = getUnreadMessageCount(message, conversation); - - const newConversation = new CometChat.Conversation( - conversationId, - conversationType, - lastMessage, - newConversationWith, - unreadMessageCount - ); - - conversations.unshift(newConversation); - setConversationList(conversations); - } - }); - }; - - /** - * - * Listener callback when a member is kicked from / has left the group - */ - const handleGroupMemberRemoval = (...options) => { - const message = options[0]; - const removedUser = options[1]; - const group = options[3]; - - getConversationFromMessage(message).then((response) => { - const { - conversationKey, - conversationId, - conversationType, - conversationWith, - conversation, - conversations, - } = response; - - if (conversationKey > -1) { - /** - * If the loggedin user is removed from the group, remove the conversation from the chats list - */ - if (loggedInUser?.current?.uid === removedUser.uid) { - conversations.splice(conversationKey, 1); - setConversationList(conversations); - } else { - const lastMessage = { ...conversation.lastMessage, ...message }; - const newConversationWith = { ...conversationWith, ...group }; - const unreadMessageCount = getUnreadMessageCount( - message, - conversation - ); - - const newConversation = new CometChat.Conversation( - conversationId, - conversationType, - lastMessage, - newConversationWith, - unreadMessageCount - ); - - conversations.splice(conversationKey, 1, newConversation); - setConversationList(conversations); - } - } - }); - }; - - /** - * - * Listener callback when a member is banned from the group - */ - const handleGroupMemberBan = (...options) => { - const message = options[0]; - const removedUser = options[1]; - const group = options[3]; - - getConversationFromMessage(message).then((response) => { - const { - conversationKey, - conversationId, - conversationType, - conversationWith, - conversation, - conversations, - } = response; - - if (conversationKey > -1) { - /** - * If the loggedin user is banned from the group, remove the conversation from the chats list - */ - if (loggedInUser?.current?.uid === removedUser.uid) { - conversations.splice(conversationKey, 1); - setConversationList(conversations); - } else { - const lastMessage = { ...conversation.lastMessage, ...message }; - const newConversationWith = { ...conversationWith, ...group }; - const unreadMessageCount = getUnreadMessageCount( - message, - conversation - ); - - const newConversation = new CometChat.Conversation( - conversationId, - conversationType, - lastMessage, - newConversationWith, - unreadMessageCount - ); - - conversations.splice(conversationKey, 1, newConversation); - setConversationList(conversations); - } - } - }); - }; - - /** - * - * Listener callback when a group member scope is updated - */ - const handleGroupMemberScopeChange = (...options) => { - const message = options[0]; - const user = options[1]; - const newScope = options[2]; - const group = options[4]; - - getConversationFromMessage(message).then((response) => { - const { - conversationKey, - conversationId, - conversationType, - conversationWith, - conversation, - conversations, - } = response; - - if (conversationKey > -1) { - const lastMessage = { ...conversation.lastMessage, ...message }; - const unreadMessageCount = getUnreadMessageCount(message, conversation); - - if (loggedInUser?.current?.uid === user.uid) { - const newConversationWith = { - ...conversationWith, - ...group, - scope: newScope, - }; - - const newConversation = new CometChat.Conversation( - conversationId, - conversationType, - lastMessage, - newConversationWith, - unreadMessageCount - ); - - conversations.splice(conversationKey, 1); - conversations.unshift(newConversation); - setConversationList(conversations); - } else { - let newConversationWith = { ...conversationWith, ...group }; - - const newConversation = new CometChat.Conversation( - conversationId, - conversationType, - lastMessage, - newConversationWith, - unreadMessageCount - ); - - conversations.splice(conversationKey, 1, newConversation); - setConversationList(conversations); - } - } - }); - }; - - /** - * - * Listener callback for typing events - */ - const handleTyping = (...options) => { - const typingData = options[0]; - const typingStarted = options[1]; - const conversations = [...conversationList]; - - let conversationKey = conversations.findIndex( - (conversation) => - conversation?.conversationType === typingData?.receiverType && - ((conversation?.conversationType === ReceiverTypeConstants.user && - conversation.conversationWith?.uid === typingData?.sender?.uid) || - (conversation.conversationType === ReceiverTypeConstants.group && - conversation.conversationWith?.guid === typingData?.receiverId)) - ); + } + }); + }; + + /** + * + * Listener callback for typing events + */ + const handleTyping = (...options) => { + const typingData = options[0]; + const typingStarted = options[1]; + const conversations = [...conversationList]; + + let conversationKey = conversations.findIndex( + (conversation) => + conversation?.conversationType === typingData?.receiverType && + ((conversation?.conversationType === ReceiverTypeConstants.user && + conversation.conversationWith?.uid === typingData?.sender?.uid) || + (conversation.conversationType === ReceiverTypeConstants.group && + conversation.conversationWith?.guid === typingData?.receiverId)) + ); - if (conversationKey > -1) { - let typingIndicatorText = ""; - if (typingStarted) { - typingIndicatorText = - typingData?.receiverType === ReceiverTypeConstants.group - ? `${typingData?.sender?.name} ${localize("IS_TYPING")}` - : localize("IS_TYPING"); - } - - const conversation = conversationList[conversationKey]; - const newConversation = { - ...conversation, - showTypingIndicator: typingStarted, - typingIndicatorText, - }; + if (conversationKey > -1) { + let typingIndicatorText = ""; + if (typingStarted) { + typingIndicatorText = + typingData?.receiverType === ReceiverTypeConstants.group + ? `${typingData?.sender?.name} ${localize("IS_TYPING")}` + : localize("IS_TYPING"); + } + + const conversation = conversationList[conversationKey]; + const newConversation = { + ...conversation, + showTypingIndicator: typingStarted, + typingIndicatorText, + }; + + conversations.splice(conversationKey, 1, newConversation); + setConversationList(conversations); + } + }; + + /** + * + * @param {Object} conversation + * Public method to update the conversation list programmatically + */ + const updateConversation = (conversation) => { + const conversationKey = conversationList.findIndex( + (eachConversation) => + eachConversation.conversationWith && + eachConversation.conversationWith.uid && + eachConversation.conversationWith.uid === + conversation?.conversationWith?.uid + ); - conversations.splice(conversationKey, 1, newConversation); - setConversationList(conversations); + if (conversationKey > -1) { + let conversations = [...conversationList]; + let conversation = conversations[conversationKey]; + let conversationWith = { + ...conversation.conversationWith, + }; + + let newConversation = { + ...conversation, + conversationWith: conversationWith, + }; + conversations.splice(conversationKey, 1, newConversation); + setConversationList(conversations); + } + }; + + const handlers = { + onUserOnline: handleUsers, + onUserOffline: handleUsers, + onTextMessageReceived: handleMessages, + onMediaMessageReceived: handleMessages, + onCustomMessageReceived: handleMessages, + onIncomingCallReceived: handleMessages, + onIncomingCallCancelled: handleMessages, + messageEdited: handleMessageActions, + onMessageDeleted: handleMessageActions, + messageRead: handleMessageReadActions, + onMemberAddedToGroup: handleGroupMemberAddition, + onGroupMemberJoined: handleGroupMemberAddition, + onGroupMemberKicked: handleGroupMemberRemoval, + onGroupMemberLeft: handleGroupMemberRemoval, + onGroupMemberBanned: handleGroupMemberBan, + onGroupMemberScopeChanged: handleGroupMemberScopeChange, + onTypingStarted: handleTyping, + onTypingEnded: handleTyping, + }; + + const handleConversations = () => { + getConversations() + .then((conversations) => { + if (conversationList.length === 0 && conversations.length === 0) { + setMessage("NO_CHATS_FOUND"); + } else { + setMessage(""); } - }; - /** - * - * @param {Object} conversation - * Public method to update the conversation list programmatically - */ - const updateConversation = (conversation) => { - const conversationKey = conversationList.findIndex( - (eachConversation) => - eachConversation.conversationWith && - eachConversation.conversationWith.uid && - eachConversation.conversationWith.uid === conversation?.conversationWith?.uid - ); - - if (conversationKey > -1) { - let conversations = [...conversationList]; - let conversation = conversations[conversationKey]; - let conversationWith = { - ...conversation.conversationWith, - }; - - let newConversation = { - ...conversation, - conversationWith: conversationWith, - }; - conversations.splice(conversationKey, 1, newConversation); - setConversationList(conversations); - } - }; - - const handlers = { - onUserOnline: handleUsers, - onUserOffline: handleUsers, - onTextMessageReceived: handleMessages, - onMediaMessageReceived: handleMessages, - onCustomMessageReceived: handleMessages, - onIncomingCallReceived: handleMessages, - onIncomingCallCancelled: handleMessages, - messageEdited: handleMessageActions, - onMessageDeleted: handleMessageActions, - messageRead: handleMessageReadActions, - onMemberAddedToGroup: handleGroupMemberAddition, - onGroupMemberJoined: handleGroupMemberAddition, - onGroupMemberKicked: handleGroupMemberRemoval, - onGroupMemberLeft: handleGroupMemberRemoval, - onGroupMemberBanned: handleGroupMemberBan, - onGroupMemberScopeChanged: handleGroupMemberScopeChange, - onTypingStarted: handleTyping, - onTypingEnded: handleTyping, - }; - - const handleConversations = () => { - getConversations() - .then((conversations) => { - if (conversationList.length === 0 && conversations.length === 0) { - setMessage("NO_CHATS_FOUND"); - } else { - setMessage(""); - } - - setConversationList((conversationList) => { - return [...conversationList, ...conversations]; - }); - }) - .catch((error) => { - CometChatConversationEvents.emit( - CometChatConversationEvents.onError, - error - ); - setMessage(("SOMETHING_WENT_WRONG")); - }); - }; - - const getConversations = () => { - return new Promise((resolve, reject) => { - conversationListManager?.current - .fetchNextConversation() - .then((conversations) => resolve(conversations)) - .catch((error) => { - CometChatConversationEvents.emit( - CometChatConversationEvents.onError, - error - ); - reject(error) - }); + setConversationList((conversationList) => { + return [...conversationList, ...conversations]; }); - }; - - const handleScroll = (event) => { - const bottom = - Math.round( - event.currentTarget.scrollHeight - event.currentTarget.scrollTop - ) === Math.round(event.currentTarget.clientHeight); - if (bottom) { - handleConversations(); - } - }; - - /** - * reset un read count - */ - const resetUnreadCount = (conversation) => { - const conversations = [...conversationList]; - const conversationKey = conversations.findIndex( - (conversationObject) => - conversationObject.conversationId === conversation.conversationId + }) + .catch((error) => { + CometChatConversationEvents.emit( + CometChatConversationEvents.onError, + error ); - if (conversationKey > -1) { - let conversation = conversations[conversationKey]; - let newConversation = { - ...conversation, - unreadMessageCount: 0, - }; - conversations.splice(conversationKey, 1, newConversation); - setConversationList(conversations); - } - }; - - /** - * update last message - */ - const updateLastMessage = (message) => { - getConversationFromMessage(message).then((response) => { - const { conversationKey, conversations, conversation } = response; - const lastMessage = { ...conversation.lastMessage }; - if (conversationKey > -1) { - let newConversation = { - ...conversation, - lastMessage: lastMessage, - }; - conversations.splice(conversationKey, 1, newConversation); - setConversationList(conversations); - } + setMessage("SOMETHING_WENT_WRONG"); + }); + }; + + const getConversations = () => { + return new Promise((resolve, reject) => { + conversationListManager?.current + .fetchNextConversation() + .then((conversations) => resolve(conversations)) + .catch((error) => { + CometChatConversationEvents.emit( + CometChatConversationEvents.onError, + error + ); + reject(error); }); - }; + }); + }; + + const handleScroll = (event) => { + const bottom = + Math.round( + event.currentTarget.scrollHeight - event.currentTarget.scrollTop + ) === Math.round(event.currentTarget.clientHeight); + if (bottom) { + handleConversations(); + } + }; + + /** + * reset un read count + */ + const resetUnreadCount = (conversation) => { + const conversations = [...conversationList]; + const conversationKey = conversations.findIndex( + (conversationObject) => + conversationObject.conversationId === conversation.conversationId + ); + if (conversationKey > -1) { + let conversation = conversations[conversationKey]; + let newConversation = { + ...conversation, + unreadMessageCount: 0, + }; + conversations.splice(conversationKey, 1, newConversation); + setConversationList(conversations); + } + }; + + // /** + // * update last edited or deleted message + // */ + const updateConversationonEditOrDeleteMessage = (message) => { + getConversationFromMessage(message).then((response) => { + setConversationList((prevConversationList) => { + let conversations = [...prevConversationList]; + let conversationKey = prevConversationList.findIndex( + (c) => c.conversationId === response.conversation.conversationId + ); - /** - * Remove conversation from the conversationlist upon delete - */ - const removeConversation = (conversation) => { - const conversationKey = conversationList.findIndex( - (c) => c.conversationId === conversation.conversationId + const latestConversation = prevConversationList[conversationKey]; + if ( + conversationKey > -1 && + latestConversation?.lastMessage?.id === message.id + ) { + let newConversation = { + ...latestConversation, + lastMessage: { ...message }, + }; + conversations.splice(conversationKey, 1, newConversation); + return [...conversations]; + } else { + return [...prevConversationList]; + } + }); + }); + }; + + /** + * update last message + */ + const updateLastMessage = (message) => { + getConversationFromMessage(message).then((response) => { + setConversationList((prevConversationList) => { + let conversations = [...prevConversationList]; + let conversationKey = prevConversationList.findIndex( + (c) => c.conversationId === response.conversation.conversationId ); if (conversationKey > -1) { - const newConversationList = [...conversationList]; - newConversationList.splice(conversationKey, 1); - setConversationList(newConversationList); + const latestConversation = prevConversationList[conversationKey]; + let newConversation = { + ...latestConversation, + lastMessage: { ...message }, + }; + conversations.splice(conversationKey, 1, newConversation); + return [...conversations]; + } else { + const { conversationKey, conversations, conversation } = response; + let newConversation = { + ...conversation, + lastMessage: { ...message }, + }; + conversations.unshift(conversationKey, 1, newConversation); + return [...conversations]; } - }; - - const deleteConversation = (conversationToBeDeleted) => { - - return new Promise((resolve, reject) => { - const conversationWith = conversationToBeDeleted?.conversationType === ReceiverTypeConstants.group - ? conversationToBeDeleted?.conversationWith?.guid - : conversationToBeDeleted?.conversationWith?.uid; - - CometChat.deleteConversation( - conversationWith, - conversationToBeDeleted?.conversationType - ) - .then((deletedConversation) => { - setShowConfirm({ - ...showConfirm, - show: false - }); - removeConversation(conversationToBeDeleted); - resolve(deletedConversation); - CometChatConversationEvents.emit( - CometChatConversationEvents.onDeleteConversation, - conversationToBeDeleted - ); - }) - - .catch((error) => { - CometChatConversationEvents.emit( - CometChatConversationEvents.onError, - conversationToBeDeleted - ); - reject(error); - }); - }); - }; - - const cancelDelete = () => setShowConfirm({ - ...showConfirm, - show: false + }); }); + }; + + /** + * Remove conversation from the conversationlist upon delete + */ + const removeConversation = (conversation) => { + const conversationKey = conversationList.findIndex( + (c) => c.conversationId === conversation.conversationId + ); - const confirmDelete = (conversation) => { - setShowConfirm({ + if (conversationKey > -1) { + const newConversationList = [...conversationList]; + newConversationList.splice(conversationKey, 1); + setConversationList(newConversationList); + } + }; + + const deleteConversation = (conversationToBeDeleted) => { + return new Promise((resolve, reject) => { + const conversationWith = + conversationToBeDeleted?.conversationType === + ReceiverTypeConstants.group + ? conversationToBeDeleted?.conversationWith?.guid + : conversationToBeDeleted?.conversationWith?.uid; + + CometChat.deleteConversation( + conversationWith, + conversationToBeDeleted?.conversationType + ) + .then((deletedConversation) => { + setShowConfirm({ ...showConfirm, - show: true, - conversation: conversation, - onCancel: cancelDelete + show: false, + }); + removeConversation(conversationToBeDeleted); + resolve(deletedConversation); + CometChatConversationEvents.emit( + CometChatConversationEvents.onDeleteConversation, + conversationToBeDeleted + ); }) - }; - const itemClickhandler = (e) => { - CometChatConversationEvents.emit( - CometChatConversationEvents.onItemClick, - e - ); - }; + .catch((error) => { + CometChatConversationEvents.emit( + CometChatConversationEvents.onError, + conversationToBeDeleted + ); + reject(error); + }); + }); + }; + const cancelDelete = () => + setShowConfirm({ + ...showConfirm, + show: false, + }); - /** - * Component hooks - */ + const confirmDelete = (conversation) => { + setShowConfirm({ + ...showConfirm, + show: true, + conversation: conversation, + onCancel: cancelDelete, + }); + }; - Hooks( - conversationType, - limit, - tags, - userAndGroupTags, - setConversationList, - conversationCallback, - conversationListManager, - handlers, - callbackData, - loggedInUser, - handleConversations, - confirmDelete + const itemClickhandler = (e) => { + CometChatConversationEvents.emit( + CometChatConversationEvents.onItemClick, + e ); + }; + + /** + * Component hooks + */ + + Hooks( + conversationType, + limit, + tags, + userAndGroupTags, + setConversationList, + conversationCallback, + conversationListManager, + loggedInUser, + handleConversations + ); + + /** + * Component template scoping + */ + + const getCustomView = (customView, props) => { + return React.createElement(customView, props); + }; + + const getMessageContainer = () => { + let messageContainer = null; + if ( + conversationList.length === 0 && + message.toLowerCase() === localize("LOADING") + ) { + /**Loading custom view */ + messageContainer = ( +
- {title} -
- {!hideCloseButton ? ( - - ) : null} -+ {title} +
+ {!hideCloseButton ? ( + + ) : null} +- {parseText()} +
{
}
loggedInUser={loggedInUserRef.current}
onClick={_smartRepliesConfiguration.onClick}
- style={smartReplyStyle(_theme)}
+ style={smartReplyStyle(_theme, _smartRepliesConfiguration)}
onClose={onClose.bind(this)}
/>
);
@@ -1251,8 +1288,11 @@ const CometChatMessageList = React.forwardRef((props, ref) => {
scrolledToBottom.bind(this) ||
_newMessageIndicatorConfiguration.onClick
}
- Icon={_newMessageIndicatorConfiguration.Icon}
- style={messageIndicatorStyle(_theme)}
+ IconURL={_newMessageIndicatorConfiguration.IconURL}
+ style={messageIndicatorStyle(
+ _theme,
+ _newMessageIndicatorConfiguration
+ )}
/>
);
}
@@ -1266,7 +1306,6 @@ const CometChatMessageList = React.forwardRef((props, ref) => {
const renderItems = () => {
// to hold date value for first message
let previousMessageDate = null;
-
return messageList.map((eachMessage) => {
// date label component
let dateSeparator = null;
@@ -1289,7 +1328,7 @@ const CometChatMessageList = React.forwardRef((props, ref) => {
const pattern = _dateConfiguration?.pattern;
const customPattern = _dateConfiguration?.customPattern;
- const dateStyle = new DateStyles({
+ const dateStyle = new DateStyle({
..._dateConfiguration?.style,
textColor:
_dateConfiguration?.style?.textColor ||
@@ -1346,7 +1385,7 @@ const CometChatMessageList = React.forwardRef((props, ref) => {
};
messageBubbleData = receivedMessageInputData;
}
- let style = {
+ let style = new MessageBubbleStyle({
width: "100%",
height: "100%",
border: "0 none",
@@ -1356,7 +1395,7 @@ const CometChatMessageList = React.forwardRef((props, ref) => {
...background,
nameTextColor: _theme.palette.accent500[_theme.palette.mode],
timestampColor: _theme.palette.accent[_theme.palette.mode],
- };
+ });
return !eachMessage.action ? (
{name.length >= 2 ? name.substring(0, 2).toUpperCase() : name}