UNPKG

@sendbird/uikit-react

Version:

Sendbird UIKit for React: A feature-rich and customizable chat UI kit with messaging, channel management, and user authentication.

829 lines (820 loc) 89.2 kB
import { _ as __assign, c as __spreadArray } from '../chunks/bundle-yl5d1NoZ.js'; import React__default, { useEffect, useCallback, useRef, useState, useReducer, useMemo } from 'react'; import { useUIKitConfig, UIKitConfigProvider } from '@sendbird/uikit-tools'; import { U as UserProfileProvider } from '../chunks/bundle-B0s_McF0.js'; import { T as ThreadReplySelectType } from '../chunks/bundle-BEx1sWnS.js'; import { m as mergeAndSortMessages, p as passUnsuccessfullMessages, s as scrollIntoLast, d as scrollToRenderedMessage, g as getAllEmojisMapFromEmojiContainer, e as getNicknamesMapFromMembers } from '../chunks/bundle-DFni3Lhf.js'; import { g as getIsReactionEnabled } from '../chunks/bundle-BSy5MmTl.js'; import { g as getStringSet } from '../chunks/bundle-C1dqPUnT.js'; import { f as format } from '../chunks/bundle-mGsud0ec.js'; import { SendingStatus, ReplyType, MessageMetaArray } from '@sendbird/chat/message'; import { K, S } from '../chunks/bundle-DEuCwnTn.js'; import { R as RESET_MESSAGES, F as FETCH_INITIAL_MESSAGES_START, a as FETCH_INITIAL_MESSAGES_SUCCESS, b as FETCH_PREV_MESSAGES_SUCCESS, P as PREV_RESULT_SIZE, c as FETCH_NEXT_MESSAGES_SUCCESS, N as NEXT_RESULT_SIZE, d as FETCH_INITIAL_MESSAGES_FAILURE, e as FETCH_PREV_MESSAGES_FAILURE, f as FETCH_NEXT_MESSAGES_FAILURE, S as SEND_MESSAGE_START, g as SEND_MESSAGE_SUCCESS, h as SEND_MESSAGE_FAILURE, i as SET_CURRENT_CHANNEL, j as SET_CHANNEL_INVALID, O as ON_MESSAGE_RECEIVED, k as ON_MESSAGE_UPDATED, l as ON_MESSAGE_THREAD_INFO_UPDATED, m as RESEND_MESSAGE_START, M as MARK_AS_READ, n as ON_MESSAGE_DELETED, o as ON_MESSAGE_DELETED_BY_REQ_ID, p as SET_EMOJI_CONTAINER, q as ON_REACTION_UPDATED, r as MESSAGE_LIST_PARAMS_CHANGED, s as ON_FILE_INFO_UPLOADED, t as ON_TYPING_STATUS_UPDATED, u as MARK_AS_UNREAD, v as useInitialMessagesFetch, w as channelActions } from '../chunks/bundle-BNjG_5V3.js'; import { c as compareIds } from '../chunks/bundle-CM73CDTO.js'; import { m as isSendableMessage, a2 as filterMessageListParams } from '../chunks/bundle-vmZ9LoYK.js'; import { GroupChannelHandler } from '@sendbird/chat/groupChannel'; import { u as uuidv4 } from '../chunks/bundle-DGh2T5IL.js'; import { u as useSendbird } from '../chunks/bundle-i_3w58Zd.js'; import { u as useReconnectOnIdle } from '../chunks/bundle-C-onA3TP.js'; import { f as SCROLL_BOTTOM_DELAY_FOR_FETCH, e as SCROLL_BOTTOM_DELAY_FOR_SEND, a as VOICE_MESSAGE_FILE_NAME, b as VOICE_MESSAGE_MIME_TYPE, i as META_ARRAY_VOICE_DURATION_KEY, j as META_ARRAY_MESSAGE_TYPE_KEY, k as META_ARRAY_MESSAGE_TYPE_VALUE__VOICE } from '../chunks/bundle-CqLLOVG5.js'; import { p as pubSubTopics, b as PublishingModuleType, P as PUBSUB_TOPICS, s as shouldPubSubPublishToChannel } from '../chunks/bundle-BOykFtQ3.js'; import { g as getCaseResolvedReplyType, a as getCaseResolvedThreadReplySelectType } from '../chunks/bundle-DK3-aB7E.js'; import { u as useSendMultipleFilesMessage } from '../chunks/bundle-CIQCAe1h.js'; import { u as useLocalization } from '../chunks/bundle-Del33VzI.js'; import { u as uikitConfigStorage } from '../chunks/bundle-YKDbjcG6.js'; import '../chunks/bundle-fdEQfX2s.js'; import '../chunks/bundle-BZGITC2g.js'; import '../utils/message/getOutgoingMessageState.js'; import '../chunks/bundle-DgosLQK9.js'; import '../chunks/bundle-BUYU9H94.js'; import '@sendbird/chat'; import '@sendbird/chat/openChannel'; var initialState = { initialized: false, loading: true, allMessages: [], /** * localMessages: pending & failed messages */ localMessages: [], stringSet: getStringSet(), currentGroupChannel: null, // for scrollup hasMorePrev: false, oldestMessageTimeStamp: 0, // for scroll down // onScrollDownCallback is added for navigation to different timestamps on messageSearch // hasMorePrev, onScrollCallback -> scroll up(default behavior) // hasMoreNext, onScrollDownCallback -> scroll down hasMoreNext: false, latestMessageTimeStamp: 0, emojiContainer: { emojiCategories: [], emojiHash: '' }, /** @deprecated Please use `unreadSinceDate` instead. * */ unreadSince: null, /** * unreadSinceDate is a date information about message unread. * It's used only for the {unreadSinceDate && <UnreadCount unreadSinceDate={unreadSinceDate} />} */ unreadSinceDate: null, isInvalid: false, readStatus: null, messageListParams: null, typingMembers: [], }; var getOldestMessageTimeStamp = function (messages) { if (messages === void 0) { messages = []; } var oldestMessage = messages[0]; return (oldestMessage && oldestMessage.createdAt) || null; }; var getLatestMessageTimeStamp = function (messages) { if (messages === void 0) { messages = []; } var latestMessage = messages[messages.length - 1]; return (latestMessage && latestMessage.createdAt) || null; }; function hasReqId(message) { return 'reqId' in message; } function channelReducer(state, action) { return K(action) .with({ type: RESET_MESSAGES }, function () { return __assign(__assign({}, state), { // when user switches channel, if the previous channel `hasMorePrev` // the onScroll gets called twice, setting hasMorePrev false prevents this hasMorePrev: false, hasMoreNext: false, allMessages: [], localMessages: [] }); }) .with({ type: FETCH_INITIAL_MESSAGES_START }, function () { return __assign(__assign({}, state), { loading: true, allMessages: state.allMessages.filter(function (m) { return isSendableMessage(m) ? m.sendingStatus !== SendingStatus.SUCCEEDED : true; }), localMessages: [] }); }) .with({ type: FETCH_INITIAL_MESSAGES_SUCCESS }, function (action) { var _a; var _b = action.payload, currentGroupChannel = _b.currentGroupChannel, messages = _b.messages; if (!((currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url) === ((_a = state.currentGroupChannel) === null || _a === void 0 ? void 0 : _a.url))) { return state; } var oldestMessageTimeStamp = getOldestMessageTimeStamp(messages); var latestMessageTimeStamp = getLatestMessageTimeStamp(messages); return __assign(__assign({}, state), { loading: false, initialized: true, hasMorePrev: true, hasMoreNext: true, oldestMessageTimeStamp: oldestMessageTimeStamp, latestMessageTimeStamp: latestMessageTimeStamp, allMessages: __spreadArray([], messages, true) }); }) .with({ type: FETCH_PREV_MESSAGES_SUCCESS }, function (action) { var _a, _b, _c, _d; var _e = action.payload, currentGroupChannel = _e.currentGroupChannel, messages = _e.messages; if (!((currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url) === ((_a = state.currentGroupChannel) === null || _a === void 0 ? void 0 : _a.url))) { return state; } var hasMorePrev = ((_b = messages === null || messages === void 0 ? void 0 : messages.length) !== null && _b !== void 0 ? _b : 0) >= ((_d = (_c = state === null || state === void 0 ? void 0 : state.messageListParams) === null || _c === void 0 ? void 0 : _c.prevResultSize) !== null && _d !== void 0 ? _d : PREV_RESULT_SIZE) + 1; var oldestMessageTimeStamp = getOldestMessageTimeStamp(messages); // Remove duplicated messages var duplicatedMessageIds = []; var updatedOldMessages = state.allMessages.map(function (msg) { var duplicatedMessage = messages.find(function (_a) { var messageId = _a.messageId; return compareIds(messageId, msg.messageId); }); if (!duplicatedMessage) { return msg; } duplicatedMessageIds.push(duplicatedMessage.messageId); return duplicatedMessage.updatedAt > msg.updatedAt ? duplicatedMessage : msg; }); var filteredNewMessages = duplicatedMessageIds.length > 0 ? messages.filter(function (msg) { return !duplicatedMessageIds.find(function (messageId) { return compareIds(messageId, msg.messageId); }); }) : messages; return __assign(__assign({}, state), { hasMorePrev: hasMorePrev, oldestMessageTimeStamp: oldestMessageTimeStamp, allMessages: __spreadArray(__spreadArray([], filteredNewMessages, true), updatedOldMessages, true) }); }) .with({ type: FETCH_NEXT_MESSAGES_SUCCESS }, function (action) { var _a, _b, _c, _d; var _e = action.payload, currentGroupChannel = _e.currentGroupChannel, messages = _e.messages; if (!((currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url) === ((_a = state.currentGroupChannel) === null || _a === void 0 ? void 0 : _a.url))) { return state; } var hasMoreNext = ((_b = messages === null || messages === void 0 ? void 0 : messages.length) !== null && _b !== void 0 ? _b : 0) === ((_d = (_c = state === null || state === void 0 ? void 0 : state.messageListParams) === null || _c === void 0 ? void 0 : _c.nextResultSize) !== null && _d !== void 0 ? _d : NEXT_RESULT_SIZE) + 1; var latestMessageTimeStamp = getLatestMessageTimeStamp(messages); // sort ~ var sortedMessages = mergeAndSortMessages(state.allMessages, messages); return __assign(__assign({}, state), { hasMoreNext: hasMoreNext, latestMessageTimeStamp: latestMessageTimeStamp, allMessages: sortedMessages }); }) .with({ type: S.union(FETCH_INITIAL_MESSAGES_FAILURE, FETCH_PREV_MESSAGES_FAILURE, FETCH_NEXT_MESSAGES_FAILURE), }, function (action) { var _a; var currentGroupChannel = action.payload.currentGroupChannel; if ((currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url) !== ((_a = state === null || state === void 0 ? void 0 : state.currentGroupChannel) === null || _a === void 0 ? void 0 : _a.url)) return state; // It shows something went wrong screen when fetching initial messages failed. var shouldInvalid = [FETCH_INITIAL_MESSAGES_FAILURE].includes(action.type); return __assign(__assign({}, state), { loading: false, isInvalid: shouldInvalid, initialized: false, allMessages: [], hasMorePrev: false, hasMoreNext: false, oldestMessageTimeStamp: null, latestMessageTimeStamp: null }); }) .with({ type: SEND_MESSAGE_START }, function (action) { // Message should not be spread here // it will loose some methods like `isUserMessage` return __assign(__assign({}, state), { localMessages: __spreadArray(__spreadArray([], state.localMessages, true), [action.payload], false) }); }) .with({ type: SEND_MESSAGE_SUCCESS }, function (action) { var message = action.payload; /** * Admin messages do not have reqId. We need to include them. */ var filteredMessages = state.allMessages.filter(function (m) { return !hasReqId(m) || (m === null || m === void 0 ? void 0 : m.reqId) !== (message === null || message === void 0 ? void 0 : message.reqId); }); // [Policy] Pending messages and failed messages // must always be at the end of the message list return __assign(__assign({}, state), { allMessages: __spreadArray(__spreadArray([], filteredMessages, true), [message], false), localMessages: state.localMessages.filter(function (m) { return hasReqId(m) && (m === null || m === void 0 ? void 0 : m.reqId) !== (message === null || message === void 0 ? void 0 : message.reqId); }) }); }) .with({ type: SEND_MESSAGE_FAILURE }, function (action) { // @ts-ignore action.payload.failed = true; return __assign(__assign({}, state), { localMessages: state.localMessages.map(function (m) { return compareIds(hasReqId(m) && m.reqId, action.payload.reqId) ? action.payload : m; }) }); }) .with({ type: SET_CURRENT_CHANNEL }, function (action) { return __assign(__assign({}, state), { currentGroupChannel: action.payload, isInvalid: false }); }) .with({ type: SET_CHANNEL_INVALID }, function () { return __assign(__assign({}, state), { currentGroupChannel: null, allMessages: [], localMessages: [], isInvalid: true }); }) .with({ type: ON_MESSAGE_RECEIVED }, function (action) { var _a, _b; var _c = action.payload, channel = _c.channel, message = _c.message; var members = channel.members; var sender = message.sender; var currentGroupChannel = state.currentGroupChannel, stringSet = state.stringSet; var currentGroupChannelUrl = currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url; if (!compareIds(channel === null || channel === void 0 ? void 0 : channel.url, currentGroupChannelUrl)) { return state; } // Excluded overlapping messages if (state.allMessages.some(function (msg) { return msg.messageId === message.messageId; })) { return state; } // Filter by userFilledQuery if (state.messageListParams && !filterMessageListParams(state.messageListParams, message)) { return state; } if (message.isAdminMessage && message.isAdminMessage()) { return __assign(__assign({}, state), { allMessages: passUnsuccessfullMessages(state.allMessages, message) }); } // Update members when sender profileUrl, nickname, friendName has been changed var senderMember = members === null || members === void 0 ? void 0 : members.find(function (m) { return (m === null || m === void 0 ? void 0 : m.userId) === (sender === null || sender === void 0 ? void 0 : sender.userId); }); if ((senderMember === null || senderMember === void 0 ? void 0 : senderMember.profileUrl) !== (sender === null || sender === void 0 ? void 0 : sender.profileUrl) || (senderMember === null || senderMember === void 0 ? void 0 : senderMember.friendName) !== (sender === null || sender === void 0 ? void 0 : sender.friendName) || (senderMember === null || senderMember === void 0 ? void 0 : senderMember.nickname) !== (sender === null || sender === void 0 ? void 0 : sender.nickname)) { // @ts-ignore channel.members = members.map(function (member) { if (member.userId === sender.userId) { return sender; } return member; }); } return __assign(__assign({}, state), { currentGroupChannel: channel, unreadSince: (_a = state.unreadSince) !== null && _a !== void 0 ? _a : format(new Date(), stringSet.DATE_FORMAT__UNREAD_SINCE), unreadSinceDate: (_b = state.unreadSinceDate) !== null && _b !== void 0 ? _b : new Date(), allMessages: passUnsuccessfullMessages(state.allMessages, message) }); }) .with({ type: ON_MESSAGE_UPDATED }, function (action) { var _a; var _b = action.payload, channel = _b.channel, message = _b.message; var currentGroupChannelUrl = ((_a = state === null || state === void 0 ? void 0 : state.currentGroupChannel) === null || _a === void 0 ? void 0 : _a.url) || ''; if (!compareIds(channel === null || channel === void 0 ? void 0 : channel.url, currentGroupChannelUrl)) { return state; // Ignore event when it is not for the current channel } if (state.messageListParams && !filterMessageListParams(state.messageListParams, message)) { // Delete the message if it doesn't match to the params anymore return __assign(__assign({}, state), { allMessages: state.allMessages.filter(function (m) { return !compareIds(m.messageId, message === null || message === void 0 ? void 0 : message.messageId); }) }); } return __assign(__assign({}, state), { allMessages: state.allMessages.map(function (m) { if (compareIds(m.messageId, message.messageId)) { return message; } if (compareIds(m.parentMessageId, message.messageId)) { m.parentMessage = message; // eslint-disable-line no-param-reassign } return m; }) }); }) .with({ type: ON_MESSAGE_THREAD_INFO_UPDATED }, function (action) { var _a; var _b = action.payload, channel = _b.channel, event = _b.event; var channelUrl = event.channelUrl, threadInfo = event.threadInfo, targetMessageId = event.targetMessageId; var currentGroupChannelUrl = ((_a = state === null || state === void 0 ? void 0 : state.currentGroupChannel) === null || _a === void 0 ? void 0 : _a.url) || ''; if (!compareIds(channel === null || channel === void 0 ? void 0 : channel.url, currentGroupChannelUrl) || !compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { return state; // Ignore event when it is not for the current channel } return __assign(__assign({}, state), { allMessages: state.allMessages.map(function (m) { if (compareIds(m.messageId, targetMessageId)) { // eslint-disable-next-line no-param-reassign m.threadInfo = threadInfo; // Upsert threadInfo to the target message } return m; }) }); }) .with({ type: RESEND_MESSAGE_START }, function (action) { return __assign(__assign({}, state), { localMessages: state.localMessages.map(function (m) { return compareIds(hasReqId(m) && m.reqId, action.payload.reqId) ? action.payload : m; }) }); }) .with({ type: MARK_AS_READ }, function (action) { var _a, _b, _c; if (((_a = state.currentGroupChannel) === null || _a === void 0 ? void 0 : _a.url) !== ((_c = (_b = action.payload) === null || _b === void 0 ? void 0 : _b.channel) === null || _c === void 0 ? void 0 : _c.url)) { return state; } return __assign(__assign({}, state), { unreadSince: null, unreadSinceDate: null }); }) .with({ type: ON_MESSAGE_DELETED }, function (action) { return __assign(__assign({}, state), { allMessages: state.allMessages.filter(function (m) { return !compareIds(m.messageId, action.payload); }) }); }) .with({ type: ON_MESSAGE_DELETED_BY_REQ_ID }, function (action) { return __assign(__assign({}, state), { localMessages: state.localMessages.filter(function (m) { return !compareIds(hasReqId(m) && m.reqId, action.payload); }) }); }) .with({ type: SET_EMOJI_CONTAINER }, function (action) { return __assign(__assign({}, state), { emojiContainer: action.payload }); }) .with({ type: ON_REACTION_UPDATED }, function (action) { return __assign(__assign({}, state), { allMessages: state.allMessages.map(function (m) { if (compareIds(m.messageId, action.payload.messageId)) { if (m.applyReactionEvent && typeof m.applyReactionEvent === 'function') { m.applyReactionEvent(action.payload); } return m; } return m; }) }); }) .with({ type: MESSAGE_LIST_PARAMS_CHANGED }, function (action) { return __assign(__assign({}, state), { messageListParams: action.payload }); }) .with({ type: ON_FILE_INFO_UPLOADED }, function (action) { var _a, _b; var _c = action.payload, channelUrl = _c.channelUrl, requestId = _c.requestId, index = _c.index, uploadableFileInfo = _c.uploadableFileInfo, error = _c.error; if (!compareIds(channelUrl, (_a = state === null || state === void 0 ? void 0 : state.currentGroupChannel) === null || _a === void 0 ? void 0 : _a.url)) { return state; } /** * We don't have to do anything here because * onFailed() will be called so handle error there instead. */ if (error) return state; var localMessages = state.localMessages; var messageToUpdate = localMessages.find(function (message) { return compareIds(hasReqId(message) && message.reqId, requestId); }); var fileInfoList = (_b = messageToUpdate .messageParams) === null || _b === void 0 ? void 0 : _b.fileInfoList; if (Array.isArray(fileInfoList)) { fileInfoList[index] = uploadableFileInfo; } return __assign(__assign({}, state), { localMessages: localMessages }); }) .with({ type: ON_TYPING_STATUS_UPDATED }, function (action) { var _a; var _b = action.payload, channel = _b.channel, typingMembers = _b.typingMembers; if (!compareIds(channel.url, (_a = state === null || state === void 0 ? void 0 : state.currentGroupChannel) === null || _a === void 0 ? void 0 : _a.url)) { return state; } return __assign(__assign({}, state), { typingMembers: typingMembers }); }) .otherwise(function () { return state; }); } var DELIVERY_RECEIPT = 'delivery_receipt'; function useHandleChannelEvents(_a, _b) { var _c, _d, _e; var sdkInit = _a.sdkInit, currentGroupChannel = _a.currentGroupChannel, disableMarkAsRead = _a.disableMarkAsRead; var sdk = _b.sdk, logger = _b.logger, scrollRef = _b.scrollRef, setQuoteMessage = _b.setQuoteMessage, messagesDispatcher = _b.messagesDispatcher; var store = useSendbird().state; var _f = store.config, markAsReadScheduler = _f.markAsReadScheduler, markAsDeliveredScheduler = _f.markAsDeliveredScheduler, disableMarkAsDelivered = _f.disableMarkAsDelivered; var canSetMarkAsDelivered = (_e = (_d = (_c = store.stores.sdkStore.sdk) === null || _c === void 0 ? void 0 : _c.appInfo) === null || _d === void 0 ? void 0 : _d.premiumFeatureList) === null || _e === void 0 ? void 0 : _e.find(function (feature) { return (feature === DELIVERY_RECEIPT); }); useEffect(function () { var _a; var channelUrl = currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url; var channelHandlerId = uuidv4(); if (channelUrl && sdkInit) { var channelHandler = { onMessageReceived: function (channel, message) { var _a, _b; if (channel.isGroupChannel() && compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { var scrollToEnd = false; try { var current = scrollRef.current; if (current) { scrollToEnd = current.offsetHeight + current.scrollTop >= current.scrollHeight - 10; } // 10 is a buffer } catch (error) { // } logger.info('Channel | useHandleChannelEvents: onMessageReceived', message); messagesDispatcher({ type: ON_MESSAGE_RECEIVED, payload: { channel: channel, message: message }, }); if (scrollToEnd && ((_a = document.getElementById('sendbird-dropdown-portal')) === null || _a === void 0 ? void 0 : _a.childElementCount) === 0 && ((_b = document.getElementById('sendbird-emoji-list-portal')) === null || _b === void 0 ? void 0 : _b.childElementCount) === 0) { // and !openContextMenu try { setTimeout(function () { return scrollIntoLast(0, scrollRef); }); if (!disableMarkAsRead) { markAsReadScheduler.push(currentGroupChannel); } if (canSetMarkAsDelivered && !disableMarkAsDelivered) { markAsDeliveredScheduler.push(currentGroupChannel); } } catch (error) { logger.warning('Channel | onMessageReceived | scroll to end failed'); } } } }, onUnreadMemberStatusUpdated: function (channel) { logger.info('Channel | useHandleChannelEvents: onUnreadMemberStatusUpdated', channel); if (compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { messagesDispatcher({ type: SET_CURRENT_CHANNEL, payload: channel, }); } }, onUserMarkedRead: function (channel, userIds) { logger.info('Channel | useHandleChannelEvents: onUserMarkedAsRead', channel, userIds); if (compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { messagesDispatcher({ type: MARK_AS_READ, payload: { channel: channel, userIds: userIds, }, }); } }, onUserMarkedUnread: function (channel, userIds) { logger.info('Channel | useHandleChannelEvents: onUserMarkedUnread', channel, userIds); // TODO:: MADOKA 이 부분에 대해서 명확하게 확인해야 함. if (compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { messagesDispatcher({ type: MARK_AS_UNREAD, payload: { channel: channel, userIds: userIds, }, }); } }, // before(onDeliveryReceiptUpdated) onUndeliveredMemberStatusUpdated: function (channel) { if (compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { logger.info('Channel | useHandleChannelEvents: onDeliveryReceiptUpdated', channel); messagesDispatcher({ type: SET_CURRENT_CHANNEL, payload: channel, }); } }, onMessageUpdated: function (channel, message) { if (channel.isGroupChannel() && compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { logger.info('Channel | useHandleChannelEvents: onMessageUpdated', message); messagesDispatcher({ type: ON_MESSAGE_UPDATED, payload: { channel: channel, message: message }, }); } }, onThreadInfoUpdated: function (channel, threadInfoUpdateEvent) { if (channel.isGroupChannel() && compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { logger.info('Channel | useHandleChannelEvents: onThreadInfoUpdated', { channel: channel, threadInfoUpdateEvent: threadInfoUpdateEvent }); messagesDispatcher({ type: ON_MESSAGE_THREAD_INFO_UPDATED, payload: { channel: channel, event: threadInfoUpdateEvent }, }); } }, onMessageDeleted: function (channel, messageId) { logger.info('Channel | useHandleChannelEvents: onMessageDeleted', { channel: channel, messageId: messageId }); setQuoteMessage(null); messagesDispatcher({ type: ON_MESSAGE_DELETED, payload: messageId, }); }, onReactionUpdated: function (channel, reactionEvent) { logger.info('Channel | useHandleChannelEvents: onReactionUpdated', { channel: channel, reactionEvent: reactionEvent }); messagesDispatcher({ type: ON_REACTION_UPDATED, payload: reactionEvent, }); }, onChannelChanged: function (channel) { if (channel.isGroupChannel() && compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { logger.info('Channel | useHandleChannelEvents: onChannelChanged', channel); messagesDispatcher({ type: SET_CURRENT_CHANNEL, payload: channel, }); } }, onChannelFrozen: function (channel) { if (channel.isGroupChannel() && compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { logger.info('Channel | useHandleChannelEvents: onChannelFrozen', channel); messagesDispatcher({ type: SET_CURRENT_CHANNEL, payload: channel, }); } }, onChannelUnfrozen: function (channel) { if (channel.isGroupChannel() && compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { logger.info('Channel | useHandleChannelEvents: onChannelUnFrozen', channel); messagesDispatcher({ type: SET_CURRENT_CHANNEL, payload: channel, }); } }, onUserMuted: function (channel, user) { if (channel.isGroupChannel() && compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { logger.info('Channel | useHandleChannelEvents: onUserMuted', { channel: channel, user: user }); messagesDispatcher({ type: SET_CURRENT_CHANNEL, payload: channel, }); } }, onUserUnmuted: function (channel, user) { if (channel.isGroupChannel() && compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { logger.info('Channel | useHandleChannelEvents: onUserUnmuted', { channel: channel, user: user }); messagesDispatcher({ type: SET_CURRENT_CHANNEL, payload: channel, }); } }, onUserBanned: function (channel, user) { var _a; if (compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl) && channel.isGroupChannel()) { logger.info('Channel | useHandleChannelEvents: onUserBanned', { channel: channel, user: user }); var isByMe = (user === null || user === void 0 ? void 0 : user.userId) === ((_a = sdk === null || sdk === void 0 ? void 0 : sdk.currentUser) === null || _a === void 0 ? void 0 : _a.userId); messagesDispatcher({ type: SET_CURRENT_CHANNEL, payload: isByMe ? null : channel, }); } }, onOperatorUpdated: function (channel, users) { if (channel.isGroupChannel() && compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { logger.info('Channel | useHandleChannelEvents: onOperatorUpdated', { channel: channel, users: users }); messagesDispatcher({ type: SET_CURRENT_CHANNEL, payload: channel, }); } }, onUserLeft: function (channel, user) { var _a; if (compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { logger.info('Channel | useHandleChannelEvents: onUserLeft', { channel: channel, user: user }); var isByMe = (user === null || user === void 0 ? void 0 : user.userId) === ((_a = sdk === null || sdk === void 0 ? void 0 : sdk.currentUser) === null || _a === void 0 ? void 0 : _a.userId); messagesDispatcher({ type: SET_CURRENT_CHANNEL, payload: isByMe ? null : channel, }); } }, onTypingStatusUpdated: function (channel) { if (compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) { logger.info('Channel | onTypingStatusUpdated', { channel: channel }); var typingMembers = channel.getTypingUsers(); messagesDispatcher({ type: ON_TYPING_STATUS_UPDATED, payload: { channel: channel, typingMembers: typingMembers, }, }); } }, }; logger.info('Channel | useHandleChannelEvents: Setup event handler', { channelHandlerId: channelHandlerId, channelHandler: channelHandler }); // Add this group channel handler to the Sendbird chat instance (_a = sdk.groupChannel) === null || _a === void 0 ? void 0 : _a.addGroupChannelHandler(channelHandlerId, new GroupChannelHandler(channelHandler)); } return function () { var _a; if ((_a = sdk === null || sdk === void 0 ? void 0 : sdk.groupChannel) === null || _a === void 0 ? void 0 : _a.removeGroupChannelHandler) { logger.info('Channel | useHandleChannelEvents: Removing message reciver handler', channelHandlerId); sdk.groupChannel.removeGroupChannelHandler(channelHandlerId); } else if (sdk === null || sdk === void 0 ? void 0 : sdk.groupChannel) { logger.error('Channel | useHandleChannelEvents: Not found the removeGroupChannelHandler'); } }; }, [currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url, sdkInit]); } function useGetChannel(_a, _b) { var channelUrl = _a.channelUrl, sdkInit = _a.sdkInit, disableMarkAsRead = _a.disableMarkAsRead; var messagesDispatcher = _b.messagesDispatcher, sdk = _b.sdk, logger = _b.logger, markAsReadScheduler = _b.markAsReadScheduler; useEffect(function () { if (channelUrl && sdkInit && sdk && sdk.groupChannel) { logger.info('Channel | useSetChannel fetching channel', channelUrl); sdk.groupChannel .getChannel(channelUrl) .then(function (groupChannel) { logger.info('Channel | useSetChannel fetched channel', groupChannel); messagesDispatcher({ type: SET_CURRENT_CHANNEL, payload: groupChannel, }); logger.info('Channel: Mark as read', groupChannel); if (!disableMarkAsRead) { markAsReadScheduler.push(groupChannel); } }) .catch(function (e) { logger.warning('Channel | useSetChannel fetch channel failed', { channelUrl: channelUrl, e: e }); messagesDispatcher({ type: SET_CHANNEL_INVALID, }); }); sdk .getAllEmoji() .then(function (emojiContainer_) { logger.info('Channel: Getting emojis success', emojiContainer_); messagesDispatcher({ type: SET_EMOJI_CONTAINER, payload: emojiContainer_, }); }) .catch(function (err) { logger.error('Channel: Getting emojis failed', err); }); } }, [channelUrl, sdkInit]); } function useHandleReconnect(_a, _b) { var isOnline = _a.isOnline, replyType = _a.replyType, disableMarkAsRead = _a.disableMarkAsRead, reconnectOnIdle = _a.reconnectOnIdle; var logger = _b.logger, sdk = _b.sdk, scrollRef = _b.scrollRef, currentGroupChannel = _b.currentGroupChannel, messagesDispatcher = _b.messagesDispatcher, markAsReadScheduler = _b.markAsReadScheduler, userFilledMessageListQuery = _b.userFilledMessageListQuery; var shouldReconnect = useReconnectOnIdle(isOnline, currentGroupChannel, reconnectOnIdle).shouldReconnect; useEffect(function () { return function () { var _a, _b, _c; // state changed from offline to online AND tab is visible if (shouldReconnect) { logger.info('Refreshing conversation state'); var isReactionEnabled = ((_a = sdk === null || sdk === void 0 ? void 0 : sdk.appInfo) === null || _a === void 0 ? void 0 : _a.useReaction) || false; var messageListParams_1 = { prevResultSize: PREV_RESULT_SIZE, isInclusive: true, includeReactions: isReactionEnabled, includeMetaArray: true, nextResultSize: NEXT_RESULT_SIZE, }; if (replyType && replyType === 'QUOTE_REPLY') { messageListParams_1.includeThreadInfo = true; messageListParams_1.includeParentMessageInfo = true; messageListParams_1.replyType = ReplyType.ONLY_REPLY_TO_CHANNEL; } if (userFilledMessageListQuery) { Object.keys(userFilledMessageListQuery).forEach(function (key) { // @ts-ignore messageListParams_1[key] = userFilledMessageListQuery[key]; }); } logger.info('Channel: Fetching messages', { currentGroupChannel: currentGroupChannel, userFilledMessageListQuery: userFilledMessageListQuery }); messagesDispatcher({ type: FETCH_INITIAL_MESSAGES_START, payload: null, }); (_b = sdk === null || sdk === void 0 ? void 0 : sdk.groupChannel) === null || _b === void 0 ? void 0 : _b.getChannel((_c = currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url) !== null && _c !== void 0 ? _c : '').then(function (groupChannel) { var lastMessageTime = new Date().getTime(); groupChannel.getMessagesByTimestamp(lastMessageTime, messageListParams_1) .then(function (messages) { messagesDispatcher({ type: FETCH_INITIAL_MESSAGES_SUCCESS, payload: { currentGroupChannel: groupChannel, messages: messages, }, }); setTimeout(function () { return scrollIntoLast(0, scrollRef); }, SCROLL_BOTTOM_DELAY_FOR_FETCH); }) .catch(function (error) { logger.error('Channel: Fetching messages failed', error); messagesDispatcher({ type: FETCH_INITIAL_MESSAGES_FAILURE, payload: { currentGroupChannel: groupChannel }, }); }); if (!disableMarkAsRead) { markAsReadScheduler.push(groupChannel); } }); } }; }, [shouldReconnect, replyType]); } function useScrollCallback(_a, _b) { var currentGroupChannel = _a.currentGroupChannel, oldestMessageTimeStamp = _a.oldestMessageTimeStamp, userFilledMessageListQuery = _a.userFilledMessageListQuery, replyType = _a.replyType; var hasMorePrev = _b.hasMorePrev, logger = _b.logger, messagesDispatcher = _b.messagesDispatcher, sdk = _b.sdk; return useCallback(function (callback) { var _a, _b; if (!hasMorePrev) { return; } var messageListParams = { prevResultSize: PREV_RESULT_SIZE, isInclusive: true, includeMetaArray: true, includeReactions: (_b = (_a = sdk === null || sdk === void 0 ? void 0 : sdk.appInfo) === null || _a === void 0 ? void 0 : _a.useReaction) !== null && _b !== void 0 ? _b : false, }; if (replyType === 'QUOTE_REPLY' || replyType === 'THREAD') { messageListParams.includeThreadInfo = true; messageListParams.includeParentMessageInfo = true; messageListParams.replyType = ReplyType.ONLY_REPLY_TO_CHANNEL; } if (userFilledMessageListQuery) { Object.keys(userFilledMessageListQuery).forEach(function (key) { // @ts-ignore messageListParams[key] = userFilledMessageListQuery[key]; }); } logger.info('Channel: Fetching messages', { currentGroupChannel: currentGroupChannel, userFilledMessageListQuery: userFilledMessageListQuery, }); currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.getMessagesByTimestamp(oldestMessageTimeStamp || new Date().getTime(), messageListParams).then(function (messages) { messagesDispatcher({ type: FETCH_PREV_MESSAGES_SUCCESS, payload: { currentGroupChannel: currentGroupChannel, messages: messages }, }); if (callback) setTimeout(function () { return callback(); }); }).catch(function () { messagesDispatcher({ type: FETCH_PREV_MESSAGES_FAILURE, payload: { currentGroupChannel: currentGroupChannel }, }); }); }, [currentGroupChannel, oldestMessageTimeStamp, replyType]); } function useScrollDownCallback(_a, _b) { var currentGroupChannel = _a.currentGroupChannel, latestMessageTimeStamp = _a.latestMessageTimeStamp, userFilledMessageListQuery = _a.userFilledMessageListQuery, hasMoreNext = _a.hasMoreNext, replyType = _a.replyType; var logger = _b.logger, messagesDispatcher = _b.messagesDispatcher, sdk = _b.sdk; return useCallback(function (cb) { var _a, _b; if (!hasMoreNext) { return; } var isReactionEnabled = (_b = (_a = sdk === null || sdk === void 0 ? void 0 : sdk.appInfo) === null || _a === void 0 ? void 0 : _a.useReaction) !== null && _b !== void 0 ? _b : false; var messageListParams = { nextResultSize: NEXT_RESULT_SIZE, isInclusive: true, includeReactions: isReactionEnabled, includeMetaArray: true, }; if (replyType && (replyType === 'QUOTE_REPLY' || replyType === 'THREAD')) { messageListParams.includeThreadInfo = true; messageListParams.includeParentMessageInfo = true; messageListParams.replyType = ReplyType.ONLY_REPLY_TO_CHANNEL; } if (userFilledMessageListQuery) { Object.keys(userFilledMessageListQuery).forEach(function (key) { // @ts-ignore messageListParams[key] = userFilledMessageListQuery[key]; }); } logger.info('Channel: Fetching later messages', { currentGroupChannel: currentGroupChannel, userFilledMessageListQuery: userFilledMessageListQuery }); currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.getMessagesByTimestamp(latestMessageTimeStamp || new Date().getTime(), messageListParams).then(function (messages) { messagesDispatcher({ type: FETCH_NEXT_MESSAGES_SUCCESS, payload: { currentGroupChannel: currentGroupChannel, messages: messages }, }); setTimeout(function () { return cb([messages, null]); }); }).catch(function (error) { logger.error('Channel: Fetching later messages failed', error); messagesDispatcher({ type: FETCH_NEXT_MESSAGES_FAILURE, payload: { currentGroupChannel: currentGroupChannel }, }); setTimeout(function () { return cb([null, error]); }); }); }, [currentGroupChannel, latestMessageTimeStamp, hasMoreNext, replyType]); } function useDeleteMessageCallback(_a, _b) { var currentGroupChannel = _a.currentGroupChannel, messagesDispatcher = _a.messagesDispatcher; var logger = _b.logger; return useCallback(function (message) { logger.info('Channel | useDeleteMessageCallback: Deleting message', message); var sendingStatus = isSendableMessage(message) ? message.sendingStatus : undefined; return new Promise(function (resolve, reject) { logger.info('Channel | useDeleteMessageCallback: Deleting message requestState:', sendingStatus); // Message is only on local if ((sendingStatus === SendingStatus.FAILED || sendingStatus === SendingStatus.PENDING) && 'reqId' in message) { logger.info('Channel | useDeleteMessageCallback: Deleted message from local:', message); messagesDispatcher({ type: ON_MESSAGE_DELETED_BY_REQ_ID, payload: message.reqId, }); resolve(); } else { logger.info('Channel | useDeleteMessageCallback: Deleting message from remote:', sendingStatus); currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.deleteMessage(message).then(function () { logger.info('Channel | useDeleteMessageCallback: Deleting message success!', message); messagesDispatcher({ type: ON_MESSAGE_DELETED, payload: message.messageId, }); resolve(); }).catch(function (err) { logger.warning('Channel | useDeleteMessageCallback: Deleting message failed!', err); reject(err); }); } }); }, [currentGroupChannel, messagesDispatcher]); } function useUpdateMessageCallback(_a, _b) { var currentGroupChannel = _a.currentGroupChannel, messagesDispatcher = _a.messagesDispatcher, onBeforeUpdateUserMessage = _a.onBeforeUpdateUserMessage, isMentionEnabled = _a.isMentionEnabled; var logger = _b.logger, pubSub = _b.pubSub; return useCallback(function (props, callback) { var messageId = props.messageId, message = props.message, mentionedUsers = props.mentionedUsers, mentionTemplate = props.mentionTemplate; var createParamsDefault = function (message) { var params = { message: message, }; if (isMentionEnabled && mentionedUsers && mentionedUsers.length > 0) { params.mentionedUsers = mentionedUsers; } if (isMentionEnabled && mentionTemplate) { params.mentionedMessageTemplate = mentionTemplate; } else { params.mentionedMessageTemplate = message; } return params; }; var shouldCreateCustomParams = onBeforeUpdateUserMessage && typeof onBeforeUpdateUserMessage === 'function'; if (shouldCreateCustomParams) { logger.info('Channel: creating params using onBeforeUpdateUserMessage', onBeforeUpdateUserMessage); } var params = shouldCreateCustomParams ? onBeforeUpdateUserMessage(message) : createParamsDefault(message); logger.info('Channel: Updating message!', params); currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.updateUserMessage(messageId, params).then(function (msg) { if (callback) { callback(null, msg); } logger.info('Channel: Updating message success!', msg); messagesDispatcher({ type: ON_MESSAGE_UPDATED, payload: { channel: currentGroupChannel, message: msg, }, }); pubSub.publish(pubSub