UNPKG

@sendbird/uikit-react

Version:

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

793 lines (784 loc) 45.6 kB
'use strict'; var _tslib = require('./bundle-Conb-pOy.js'); var React = require('react'); var message = require('@sendbird/chat/message'); var groupChannel = require('@sendbird/chat/groupChannel'); var uikitTools = require('@sendbird/uikit-tools'); var UserProfileContext = require('./bundle-Bnb8seJF.js'); var index$1 = require('./bundle-19BZVS4G.js'); var SendbirdContext = require('./bundle-B19RHFpR.js'); var utils = require('./bundle-PVDrKOjZ.js'); var useSendbird = require('./bundle-Bq15P9qk.js'); var getIsReactionEnabled = require('./bundle-CXbYckbN.js'); var resolvedReplyType = require('./bundle-BPUhuptz.js'); var pubSub_topics = require('./bundle-dUH189qO.js'); var _const = require('./bundle-BLz2EOZ5.js'); var useDeepCompareEffect = require('./bundle-CxArG0ag.js'); var utils$1 = require('./bundle-CkQrhwR6.js'); var SendbirdChat = require('@sendbird/chat'); var index = require('./bundle-Dobj18FB.js'); var consts = require('./bundle-Cfh78Xnm.js'); function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; } var React__default = /*#__PURE__*/_interopDefaultCompat(React); var pass = function (value) { return value; }; /** * @description This hook controls common processes related to message sending, updating. * */ function useMessageActions(params) { var _this = this; var _a = params.onBeforeSendUserMessage, onBeforeSendUserMessage = _a === void 0 ? pass : _a, _b = params.onBeforeSendFileMessage, onBeforeSendFileMessage = _b === void 0 ? pass : _b, _c = params.onBeforeUpdateUserMessage, onBeforeUpdateUserMessage = _c === void 0 ? pass : _c, _d = params.onBeforeSendVoiceMessage, onBeforeSendVoiceMessage = _d === void 0 ? pass : _d, _e = params.onBeforeSendMultipleFilesMessage, onBeforeSendMultipleFilesMessage = _e === void 0 ? pass : _e, sendFileMessage = params.sendFileMessage, sendMultipleFilesMessage = params.sendMultipleFilesMessage, sendUserMessage = params.sendUserMessage, updateUserMessage = params.updateUserMessage, updateFileMessage = params.updateFileMessage, resendMessage = params.resendMessage, deleteMessage = params.deleteMessage, resetNewMessages = params.resetNewMessages, scrollToBottom = params.scrollToBottom, quoteMessage = params.quoteMessage, replyType = params.replyType, currentChannel = params.currentChannel; var _f = useSendbird.useSendbird().state, eventHandlers = _f.eventHandlers, pubSub = _f.config.pubSub; var buildInternalMessageParams = React.useCallback(function (basicParams) { var messageParams = _tslib.__assign({}, basicParams); if (params.quoteMessage && replyType !== 'NONE') { messageParams.isReplyToChannel = true; messageParams.parentMessageId = quoteMessage === null || quoteMessage === void 0 ? void 0 : quoteMessage.messageId; } return messageParams; }, [replyType, quoteMessage]); // This is a hack for the hotfix of following issue // https://sendbird.atlassian.net/browse/SBISSUE-17029 var asyncScrollToBottom = React.useCallback(function () { setTimeout(scrollToBottom, 0); }, [scrollToBottom]); var processParams = React.useCallback(function (handler, params, type) { return _tslib.__awaiter(_this, void 0, void 0, function () { var result, error_1; return _tslib.__generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); return [4 /*yield*/, handler(params)]; case 1: result = _a.sent(); return [2 /*return*/, (result === undefined ? params : result)]; case 2: error_1 = _a.sent(); if (typeof (eventHandlers === null || eventHandlers === void 0 ? void 0 : eventHandlers.message) === 'object') { index.K(type) .with('file', 'voice', function () { var _a, _b, _c, _d; if (params.file) { (_b = (_a = eventHandlers.message).onFileUploadFailed) === null || _b === void 0 ? void 0 : _b.call(_a, error_1); } (_d = (_c = eventHandlers.message).onSendMessageFailed) === null || _d === void 0 ? void 0 : _d.call(_c, params, error_1); }) .with('multipleFiles', function () { var _a, _b, _c, _d; if (params.fileInfoList) { (_b = (_a = eventHandlers.message).onFileUploadFailed) === null || _b === void 0 ? void 0 : _b.call(_a, error_1); } (_d = (_c = eventHandlers.message).onSendMessageFailed) === null || _d === void 0 ? void 0 : _d.call(_c, params, error_1); }) .with('user', function () { var _a, _b; (_b = (_a = eventHandlers.message).onSendMessageFailed) === null || _b === void 0 ? void 0 : _b.call(_a, params, error_1); }) .with('update', function () { var _a, _b; (_b = (_a = eventHandlers.message).onUpdateMessageFailed) === null || _b === void 0 ? void 0 : _b.call(_a, params, error_1); }) .exhaustive(); } throw error_1; case 3: return [2 /*return*/]; } }); }); }, [eventHandlers]); return { sendUserMessage: React.useCallback(function (params) { return _tslib.__awaiter(_this, void 0, void 0, function () { var internalParams, processedParams, message; return _tslib.__generator(this, function (_a) { switch (_a.label) { case 0: internalParams = buildInternalMessageParams(params); return [4 /*yield*/, processParams(onBeforeSendUserMessage, internalParams, 'user')]; case 1: processedParams = _a.sent(); return [4 /*yield*/, sendUserMessage(processedParams, asyncScrollToBottom)]; case 2: message = _a.sent(); pubSub.publish(pubSub_topics.PUBSUB_TOPICS.SEND_USER_MESSAGE, { channel: currentChannel, message: message, publishingModules: [pubSub_topics.PublishingModuleType.CHANNEL], }); return [2 /*return*/, message]; } }); }); }, [buildInternalMessageParams, sendUserMessage, scrollToBottom, processParams]), sendFileMessage: React.useCallback(function (params) { return _tslib.__awaiter(_this, void 0, void 0, function () { var internalParams, processedParams, message; return _tslib.__generator(this, function (_a) { switch (_a.label) { case 0: internalParams = buildInternalMessageParams(params); return [4 /*yield*/, processParams(onBeforeSendFileMessage, internalParams, 'file')]; case 1: processedParams = _a.sent(); return [4 /*yield*/, sendFileMessage(processedParams, asyncScrollToBottom)]; case 2: message = _a.sent(); pubSub.publish(pubSub_topics.PUBSUB_TOPICS.SEND_FILE_MESSAGE, { channel: currentChannel, message: message, publishingModules: [pubSub_topics.PublishingModuleType.CHANNEL], }); return [2 /*return*/, message]; } }); }); }, [buildInternalMessageParams, sendFileMessage, scrollToBottom, processParams]), sendMultipleFilesMessage: React.useCallback(function (params) { return _tslib.__awaiter(_this, void 0, void 0, function () { var internalParams, processedParams, message; return _tslib.__generator(this, function (_a) { switch (_a.label) { case 0: internalParams = buildInternalMessageParams(params); return [4 /*yield*/, processParams(onBeforeSendMultipleFilesMessage, internalParams, 'multipleFiles')]; case 1: processedParams = _a.sent(); return [4 /*yield*/, sendMultipleFilesMessage(processedParams, asyncScrollToBottom)]; case 2: message = _a.sent(); pubSub.publish(pubSub_topics.PUBSUB_TOPICS.SEND_FILE_MESSAGE, { channel: currentChannel, message: message, publishingModules: [pubSub_topics.PublishingModuleType.CHANNEL], }); return [2 /*return*/, message]; } }); }); }, [buildInternalMessageParams, sendMultipleFilesMessage, scrollToBottom, processParams]), sendVoiceMessage: React.useCallback(function (params, duration) { return _tslib.__awaiter(_this, void 0, void 0, function () { var internalParams, processedParams; return _tslib.__generator(this, function (_a) { switch (_a.label) { case 0: internalParams = buildInternalMessageParams(_tslib.__assign(_tslib.__assign({}, params), { fileName: consts.VOICE_MESSAGE_FILE_NAME, mimeType: consts.VOICE_MESSAGE_MIME_TYPE, metaArrays: [ new message.MessageMetaArray({ key: consts.META_ARRAY_VOICE_DURATION_KEY, value: ["".concat(duration)], }), new message.MessageMetaArray({ key: consts.META_ARRAY_MESSAGE_TYPE_KEY, value: [consts.META_ARRAY_MESSAGE_TYPE_VALUE__VOICE], }), ] })); return [4 /*yield*/, processParams(onBeforeSendVoiceMessage, internalParams, 'voice')]; case 1: processedParams = _a.sent(); return [2 /*return*/, sendFileMessage(processedParams, asyncScrollToBottom)]; } }); }); }, [buildInternalMessageParams, sendFileMessage, scrollToBottom, processParams]), updateUserMessage: React.useCallback(function (messageId, params) { return _tslib.__awaiter(_this, void 0, void 0, function () { var internalParams, processedParams; return _tslib.__generator(this, function (_a) { switch (_a.label) { case 0: internalParams = buildInternalMessageParams(params); return [4 /*yield*/, processParams(onBeforeUpdateUserMessage, internalParams, 'update')]; case 1: processedParams = _a.sent(); return [2 /*return*/, updateUserMessage(messageId, processedParams) .then(function (message) { pubSub.publish(pubSub_topics.PUBSUB_TOPICS.UPDATE_USER_MESSAGE, { channel: currentChannel, message: message, publishingModules: [pubSub_topics.PublishingModuleType.CHANNEL], }); return message; })]; } }); }); }, [buildInternalMessageParams, updateUserMessage, processParams, currentChannel === null || currentChannel === void 0 ? void 0 : currentChannel.url]), updateFileMessage: updateFileMessage, resendMessage: resendMessage, deleteMessage: deleteMessage, resetNewMessages: resetNewMessages, }; } var useGroupChannel = function () { var _a, _b, _c; var store = React.useContext(GroupChannelContext); if (!store) throw new Error('useGroupChannel must be used within a GroupChannelProvider'); var config = useSendbird.useSendbird().state.config; var markAsReadScheduler = config.markAsReadScheduler; var state = SendbirdContext.shimExports.useSyncExternalStore(store.subscribe, store.getState); var setAnimatedMessageId = React.useCallback(function (messageId) { store.setState(function (state) { return (_tslib.__assign(_tslib.__assign({}, state), { animatedMessageId: messageId })); }); }, []); var setIsScrollBottomReached = React.useCallback(function (isReached) { store.setState(function (state) { return (_tslib.__assign(_tslib.__assign({}, state), { isScrollBottomReached: isReached })); }); }, []); var scrollToBottom = React.useCallback(function (animated) { return _tslib.__awaiter(void 0, void 0, void 0, function () { return _tslib.__generator(this, function (_a) { switch (_a.label) { case 0: if (!state.scrollRef.current) return [2 /*return*/]; setAnimatedMessageId(null); setIsScrollBottomReached(true); if (!(config.isOnline && state.hasNext())) return [3 /*break*/, 2]; return [4 /*yield*/, state.resetWithStartingPoint(Number.MAX_SAFE_INTEGER)]; case 1: _a.sent(); _a.label = 2; case 2: state.scrollPubSub.publish('scrollToBottom', { animated: animated }); if (state.currentChannel && !state.hasNext()) { state.resetNewMessages(); if (!state.disableMarkAsRead) { if (!config.groupChannel.enableMarkAsUnread && state.currentChannel.myMemberState !== 'none') { markAsReadScheduler.push(state.currentChannel); } } } return [2 /*return*/]; } }); }); }, [state.scrollRef.current, config.isOnline, markAsReadScheduler, config.groupChannel.enableMarkAsUnread]); var markAsReadAll = React.useCallback(function (channel) { if (config.isOnline && !state.disableMarkAsRead && channel) { markAsReadScheduler === null || markAsReadScheduler === void 0 ? void 0 : markAsReadScheduler.push(channel); } }, [config.isOnline, state.disableMarkAsRead]); var scrollToMessage = React.useCallback(function (createdAt, messageId, messageFocusAnimated, scrollAnimated) { return _tslib.__awaiter(void 0, void 0, void 0, function () { var element, parentNode, clickHandler, message, topOffset; return _tslib.__generator(this, function (_a) { switch (_a.label) { case 0: element = state.scrollRef.current; parentNode = element === null || element === void 0 ? void 0 : element.parentNode; clickHandler = { activate: function () { if (!element || !parentNode) return; element.style.pointerEvents = 'auto'; parentNode.style.cursor = 'auto'; }, deactivate: function () { if (!element || !parentNode) return; element.style.pointerEvents = 'none'; parentNode.style.cursor = 'wait'; }, }; clickHandler.deactivate(); setAnimatedMessageId(null); message = state.messages.find(function (it) { return it.messageId === messageId || it.createdAt === createdAt; }); if (!message) return [3 /*break*/, 1]; topOffset = utils.getMessageTopOffset(message.createdAt); if (topOffset) state.scrollPubSub.publish('scroll', { top: topOffset, animated: scrollAnimated }); if (messageFocusAnimated !== null && messageFocusAnimated !== void 0 ? messageFocusAnimated : true) setAnimatedMessageId(messageId); return [3 /*break*/, 3]; case 1: if (!state.initialized) return [3 /*break*/, 3]; return [4 /*yield*/, state.resetWithStartingPoint(createdAt)]; case 2: _a.sent(); setTimeout(function () { var topOffset = utils.getMessageTopOffset(createdAt); if (topOffset) { state.scrollPubSub.publish('scroll', { top: topOffset, lazy: false, animated: scrollAnimated, }); } if (messageFocusAnimated !== null && messageFocusAnimated !== void 0 ? messageFocusAnimated : true) setAnimatedMessageId(messageId); }); _a.label = 3; case 3: clickHandler.activate(); return [2 /*return*/]; } }); }); }, [ setAnimatedMessageId, state.initialized, state.scrollRef.current, (_a = state.messages) === null || _a === void 0 ? void 0 : _a.map(function (it) { return it === null || it === void 0 ? void 0 : it.messageId; }), ]); var toggleReaction = React.useCallback(function (message, emojiKey, isReacted) { if (!state.currentChannel) return; if (isReacted) { state.currentChannel.deleteReaction(message, emojiKey) .catch(function (error) { var _a; (_a = config.logger) === null || _a === void 0 ? void 0 : _a.warning('Failed to delete reaction:', error); }); } else { state.currentChannel.addReaction(message, emojiKey) .catch(function (error) { var _a; (_a = config.logger) === null || _a === void 0 ? void 0 : _a.warning('Failed to add reaction:', error); }); } }, [(_b = state.currentChannel) === null || _b === void 0 ? void 0 : _b.deleteReaction, (_c = state.currentChannel) === null || _c === void 0 ? void 0 : _c.addReaction]); var messageActions = useMessageActions(_tslib.__assign(_tslib.__assign({}, state), { scrollToBottom: scrollToBottom })); var setCurrentChannel = React.useCallback(function (channel) { store.setState(function (state) { return (_tslib.__assign(_tslib.__assign({}, state), { currentChannel: channel, fetchChannelError: null, quoteMessage: null, animatedMessageId: null, nicknamesMap: channel ? new Map(channel.members.map(function (_a) { var userId = _a.userId, nickname = _a.nickname; return [userId, nickname]; })) : new Map() })); }, true); }, []); var handleChannelError = React.useCallback(function (error) { store.setState(function (state) { return (_tslib.__assign(_tslib.__assign({}, state), { currentChannel: null, fetchChannelError: error, quoteMessage: null, animatedMessageId: null })); }); }, []); var setQuoteMessage = React.useCallback(function (message) { store.setState(function (state) { return (_tslib.__assign(_tslib.__assign({}, state), { quoteMessage: message })); }); }, []); var setReadStateChanged = React.useCallback(function (readState) { store.setState(function (state) { return (_tslib.__assign(_tslib.__assign({}, state), { readState: readState })); }); }, []); var setFirstUnreadMessageId = React.useCallback(function (messageId) { store.setState(function (state) { return (_tslib.__assign(_tslib.__assign({}, state), { firstUnreadMessageId: messageId })); }); }, []); var actions = React.useMemo(function () { return _tslib.__assign({ setCurrentChannel: setCurrentChannel, handleChannelError: handleChannelError, markAsReadAll: markAsReadAll, markAsUnread: state.markAsUnread, setReadStateChanged: setReadStateChanged, setFirstUnreadMessageId: setFirstUnreadMessageId, setQuoteMessage: setQuoteMessage, scrollToBottom: scrollToBottom, scrollToMessage: scrollToMessage, toggleReaction: toggleReaction, setAnimatedMessageId: setAnimatedMessageId, setIsScrollBottomReached: setIsScrollBottomReached }, messageActions); }, [ setCurrentChannel, handleChannelError, markAsReadAll, state.markAsUnread, setReadStateChanged, setFirstUnreadMessageId, setQuoteMessage, scrollToBottom, scrollToMessage, toggleReaction, setAnimatedMessageId, setIsScrollBottomReached, messageActions, ]); return { state: state, actions: actions }; }; function useMessageListScroll(behavior, deps) { if (deps === void 0) { deps = []; } var scrollRef = React.useRef(null); var scrollPositionRef = React.useRef(0); var scrollDistanceFromBottomRef = React.useRef(0); var scrollPubSub = React.useState(function () { return index$1.pubSubFactory({ publishSynchronous: true }); })[0]; var setIsScrollBottomReached = useGroupChannel().actions.setIsScrollBottomReached; // SideEffect: Reset scroll state React.useLayoutEffect(function () { scrollPositionRef.current = 0; scrollDistanceFromBottomRef.current = 0; setIsScrollBottomReached(true); if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, deps); React.useLayoutEffect(function () { var unsubscribes = []; unsubscribes.push(scrollPubSub.subscribe('scrollToBottom', function (_a) { var resolve = _a.resolve, animated = _a.animated; runCallback(function () { if (!scrollRef.current) { if (resolve) resolve(); return; } if (scrollRef.current.scroll) { scrollRef.current.scroll({ top: scrollRef.current.scrollHeight, behavior: getScrollBehavior(behavior, animated) }); } else { scrollRef.current.scrollTop = scrollRef.current.scrollHeight; } // Update data by manual update scrollDistanceFromBottomRef.current = 0; setIsScrollBottomReached(true); if (resolve) resolve(); }); })); unsubscribes.push(scrollPubSub.subscribe('scroll', function (_a) { var top = _a.top, animated = _a.animated, lazy = _a.lazy, resolve = _a.resolve; runCallback(function () { if (!scrollRef.current || typeof top !== 'number') { resolve === null || resolve === void 0 ? void 0 : resolve(); return; } var _a = scrollRef.current, scrollTop = _a.scrollTop, scrollHeight = _a.scrollHeight, clientHeight = _a.clientHeight; if (scrollRef.current.scroll) { scrollRef.current.scroll({ top: top, behavior: getScrollBehavior(behavior, animated) }); } else { scrollRef.current.scrollTop = top; } // Update data by manual update scrollDistanceFromBottomRef.current = Math.max(0, scrollHeight - scrollTop - clientHeight); setIsScrollBottomReached(scrollDistanceFromBottomRef.current === 0); resolve === null || resolve === void 0 ? void 0 : resolve(); }, lazy); })); return function () { unsubscribes.forEach(function (_a) { var remove = _a.remove; return remove(); }); }; }, [behavior]); return { scrollRef: scrollRef, scrollPubSub: scrollPubSub, scrollDistanceFromBottomRef: scrollDistanceFromBottomRef, scrollPositionRef: scrollPositionRef, }; } function runCallback(callback, lazy) { if (lazy === void 0) { lazy = true; } if (lazy) { setTimeout(function () { callback(); }); } else { callback(); } } function getScrollBehavior(behavior, animated) { if (typeof animated === 'boolean') return animated ? 'smooth' : 'auto'; return behavior; } var initialState = function () { return ({ currentChannel: null, channelUrl: '', fetchChannelError: null, nicknamesMap: new Map(), initialized: false, loading: true, messages: [], quoteMessage: null, animatedMessageId: null, isScrollBottomReached: true, readState: null, scrollRef: { current: null }, scrollDistanceFromBottomRef: { current: 0 }, scrollPositionRef: { current: 0 }, messageInputRef: { current: null }, isReactionEnabled: false, isMessageGroupingEnabled: true, isMultipleFilesMessageEnabled: false, showSearchIcon: true, replyType: 'NONE', threadReplySelectType: _const.ThreadReplySelectType.PARENT, disableMarkAsRead: false, scrollBehavior: 'auto', scrollPubSub: null, }); }; var GroupChannelContext = React.createContext(null); var createGroupChannelStore = function (props) { return SendbirdContext.createStore(_tslib.__assign(_tslib.__assign({}, initialState()), props)); }; var InternalGroupChannelProvider = function (props) { var children = props.children; var defaultProps = utils$1.deleteNullish({ channelUrl: props === null || props === void 0 ? void 0 : props.channelUrl, renderUserProfile: props === null || props === void 0 ? void 0 : props.renderUserProfile, disableUserProfile: props === null || props === void 0 ? void 0 : props.disableUserProfile, onUserProfileMessage: props === null || props === void 0 ? void 0 : props.onUserProfileMessage, onStartDirectMessage: props === null || props === void 0 ? void 0 : props.onStartDirectMessage, isReactionEnabled: props === null || props === void 0 ? void 0 : props.isReactionEnabled, isMessageGroupingEnabled: props === null || props === void 0 ? void 0 : props.isMessageGroupingEnabled, isMultipleFilesMessageEnabled: props === null || props === void 0 ? void 0 : props.isMultipleFilesMessageEnabled, showSearchIcon: props === null || props === void 0 ? void 0 : props.showSearchIcon, threadReplySelectType: props === null || props === void 0 ? void 0 : props.threadReplySelectType, disableMarkAsRead: props === null || props === void 0 ? void 0 : props.disableMarkAsRead, scrollBehavior: props === null || props === void 0 ? void 0 : props.scrollBehavior, forceLeftToRightMessageLayout: props === null || props === void 0 ? void 0 : props.forceLeftToRightMessageLayout, startingPoint: props === null || props === void 0 ? void 0 : props.startingPoint, animatedMessageId: props === null || props === void 0 ? void 0 : props.animatedMessageId, onMessageAnimated: props === null || props === void 0 ? void 0 : props.onMessageAnimated, messageListQueryParams: props === null || props === void 0 ? void 0 : props.messageListQueryParams, filterEmojiCategoryIds: props === null || props === void 0 ? void 0 : props.filterEmojiCategoryIds, onBeforeSendUserMessage: props === null || props === void 0 ? void 0 : props.onBeforeSendUserMessage, onBeforeSendFileMessage: props === null || props === void 0 ? void 0 : props.onBeforeSendFileMessage, onBeforeSendVoiceMessage: props === null || props === void 0 ? void 0 : props.onBeforeSendVoiceMessage, onBeforeSendMultipleFilesMessage: props === null || props === void 0 ? void 0 : props.onBeforeSendMultipleFilesMessage, onBeforeUpdateUserMessage: props === null || props === void 0 ? void 0 : props.onBeforeUpdateUserMessage, onBeforeDownloadFileMessage: props === null || props === void 0 ? void 0 : props.onBeforeDownloadFileMessage, onBackClick: props === null || props === void 0 ? void 0 : props.onBackClick, onChatHeaderActionClick: props === null || props === void 0 ? void 0 : props.onChatHeaderActionClick, onReplyInThreadClick: props === null || props === void 0 ? void 0 : props.onReplyInThreadClick, onSearchClick: props === null || props === void 0 ? void 0 : props.onSearchClick, onQuoteMessageClick: props === null || props === void 0 ? void 0 : props.onQuoteMessageClick, renderUserMentionItem: props === null || props === void 0 ? void 0 : props.renderUserMentionItem, }); var storeRef = React.useRef(createGroupChannelStore(defaultProps)); return (React__default.default.createElement(GroupChannelContext.Provider, { value: storeRef.current }, children)); }; var GroupChannelManager = function (props) { var _a, _b, _c; var channelUrl = props.channelUrl, children = props.children, moduleReactionEnabled = props.isReactionEnabled, moduleReplyType = props.replyType, moduleThreadReplySelectType = props.threadReplySelectType, _d = props.isMessageGroupingEnabled, isMessageGroupingEnabled = _d === void 0 ? true : _d, isMultipleFilesMessageEnabled = props.isMultipleFilesMessageEnabled, showSearchIcon = props.showSearchIcon, _e = props.disableMarkAsRead, disableMarkAsRead = _e === void 0 ? false : _e, _f = props.scrollBehavior, scrollBehavior = _f === void 0 ? 'auto' : _f, startingPoint = props.startingPoint, _animatedMessageId = props.animatedMessageId, messageListQueryParams = props.messageListQueryParams, onBeforeSendUserMessage = props.onBeforeSendUserMessage, onBeforeSendFileMessage = props.onBeforeSendFileMessage, onBeforeSendVoiceMessage = props.onBeforeSendVoiceMessage, onBeforeSendMultipleFilesMessage = props.onBeforeSendMultipleFilesMessage, onBeforeUpdateUserMessage = props.onBeforeUpdateUserMessage, onBeforeDownloadFileMessage = props.onBeforeDownloadFileMessage, onMessageAnimated = props.onMessageAnimated, onBackClick = props.onBackClick, onChatHeaderActionClick = props.onChatHeaderActionClick, onReplyInThreadClick = props.onReplyInThreadClick, onSearchClick = props.onSearchClick, onQuoteMessageClick = props.onQuoteMessageClick, renderUserMentionItem = props.renderUserMentionItem, filterEmojiCategoryIds = props.filterEmojiCategoryIds; var _g = useGroupChannel(), state = _g.state, actions = _g.actions; var updateState = useGroupChannelStore().updateState; var _h = useSendbird.useSendbird().state, config = _h.config, stores = _h.stores; var sdkStore = stores.sdkStore; var userId = config.userId, markAsReadScheduler = config.markAsReadScheduler, logger = config.logger, pubSub = config.pubSub; // ScrollHandler initialization var _j = useMessageListScroll(scrollBehavior, [(_a = state.currentChannel) === null || _a === void 0 ? void 0 : _a.url]), scrollRef = _j.scrollRef, scrollPubSub = _j.scrollPubSub, scrollDistanceFromBottomRef = _j.scrollDistanceFromBottomRef, scrollPositionRef = _j.scrollPositionRef; var isScrollBottomReached = state.isScrollBottomReached; // Configuration resolution var resolvedReplyType$1 = resolvedReplyType.getCaseResolvedReplyType(moduleReplyType !== null && moduleReplyType !== void 0 ? moduleReplyType : config.groupChannel.replyType).upperCase; var resolvedThreadReplySelectType = resolvedReplyType.getCaseResolvedThreadReplySelectType(moduleThreadReplySelectType !== null && moduleThreadReplySelectType !== void 0 ? moduleThreadReplySelectType : config.groupChannel.threadReplySelectType).upperCase; var replyType = resolvedReplyType.getCaseResolvedReplyType(moduleReplyType !== null && moduleReplyType !== void 0 ? moduleReplyType : config.groupChannel.replyType).upperCase; var resolvedIsReactionEnabled = getIsReactionEnabled.getIsReactionEnabled({ channel: state.currentChannel, config: config, moduleLevel: moduleReactionEnabled, }); var chatReplyType = uikitTools.useIIFE(function () { if (replyType === 'NONE') return message.ReplyType.NONE; return message.ReplyType.ONLY_REPLY_TO_CHANNEL; }); var markAsUnreadSourceRef = React.useRef(undefined); var markAsUnread = React.useCallback(function (message, source) { var _a, _b, _c, _d; if (!config.groupChannel.enableMarkAsUnread) return; if (!state.currentChannel) { (_a = logger === null || logger === void 0 ? void 0 : logger.error) === null || _a === void 0 ? void 0 : _a.call(logger, 'GroupChannelProvider: channel is required for markAsUnread'); return; } try { if (state.currentChannel.markAsUnread) { state.currentChannel.markAsUnread(message); (_b = logger === null || logger === void 0 ? void 0 : logger.info) === null || _b === void 0 ? void 0 : _b.call(logger, 'GroupChannelProvider: markAsUnread called for message', { messageId: message.messageId, source: source || 'unknown', }); markAsUnreadSourceRef.current = source || 'internal'; } else { (_c = logger === null || logger === void 0 ? void 0 : logger.error) === null || _c === void 0 ? void 0 : _c.call(logger, 'GroupChannelProvider: markAsUnread method not available in current SDK version'); } } catch (error) { (_d = logger === null || logger === void 0 ? void 0 : logger.error) === null || _d === void 0 ? void 0 : _d.call(logger, 'GroupChannelProvider: markAsUnread failed', error); } }, [state.currentChannel, logger, config.groupChannel.enableMarkAsUnread]); // Message Collection setup var messageDataSource = uikitTools.useGroupChannelMessages(sdkStore.sdk, state.currentChannel, { startingPoint: startingPoint, replyType: chatReplyType, collectionCreator: getCollectionCreator(state.currentChannel, messageListQueryParams), shouldCountNewMessages: function () { return !isScrollBottomReached; }, markAsRead: function (channels) { if (!config.groupChannel.enableMarkAsUnread) { if (isScrollBottomReached && !disableMarkAsRead) { channels.forEach(function (it) { return markAsReadScheduler.push(it); }); } } }, onMessagesReceived: function (messages) { if (isScrollBottomReached && utils.isContextMenuClosed() // Note: this shouldn't happen ideally, but it happens on re-rendering GroupChannelManager // even though the next messages and the current messages length are the same. // So added this condition to check if they are the same to prevent unnecessary calling scrollToBottom action && messages.length !== state.messages.length) { setTimeout(function () { return _tslib.__awaiter(void 0, void 0, void 0, function () { return _tslib.__generator(this, function (_a) { return [2 /*return*/, actions.scrollToBottom(true)]; }); }); }, 10); } }, onChannelDeleted: function () { actions.setCurrentChannel(null); onBackClick === null || onBackClick === void 0 ? void 0 : onBackClick(); }, onCurrentUserBanned: function () { actions.setCurrentChannel(null); onBackClick === null || onBackClick === void 0 ? void 0 : onBackClick(); }, onChannelUpdated: function (channel, ctx) { if (ctx.source === SendbirdChat.CollectionEventSource.EVENT_CHANNEL_UNREAD && ctx.userIds.includes(userId)) { actions.setReadStateChanged('unread'); } if (ctx.source === SendbirdChat.CollectionEventSource.EVENT_CHANNEL_READ && ctx.userIds.includes(userId)) { actions.setReadStateChanged('read'); } actions.setCurrentChannel(channel); }, logger: logger, }); // Channel initialization uikitTools.useAsyncEffect(function () { return _tslib.__awaiter(void 0, void 0, void 0, function () { var channel, error_1; var _a; return _tslib.__generator(this, function (_b) { switch (_b.label) { case 0: if (!(sdkStore.initialized && channelUrl)) return [3 /*break*/, 4]; _b.label = 1; case 1: _b.trys.push([1, 3, , 4]); return [4 /*yield*/, sdkStore.sdk.groupChannel.getChannel(channelUrl)]; case 2: channel = _b.sent(); actions.setCurrentChannel(channel); return [3 /*break*/, 4]; case 3: error_1 = _b.sent(); actions.handleChannelError(error_1); (_a = logger === null || logger === void 0 ? void 0 : logger.error) === null || _a === void 0 ? void 0 : _a.call(logger, 'GroupChannelProvider: error when fetching channel', error_1); return [3 /*break*/, 4]; case 4: return [2 /*return*/]; } }); }); }, [sdkStore.initialized, sdkStore.sdk, channelUrl]); // Message sync effect uikitTools.useAsyncLayoutEffect(function () { return _tslib.__awaiter(void 0, void 0, void 0, function () { var handleExternalMessage, subscriptions; return _tslib.__generator(this, function (_a) { if (messageDataSource.initialized) { actions.scrollToBottom(); } handleExternalMessage = function (data) { var _a; if (data.channel.url === ((_a = state.currentChannel) === null || _a === void 0 ? void 0 : _a.url)) { actions.scrollToBottom(true); } }; if ((pubSub === null || pubSub === void 0 ? void 0 : pubSub.subscribe) === undefined) return [2 /*return*/]; subscriptions = [ pubSub.subscribe(pubSub_topics.pubSubTopics.SEND_USER_MESSAGE, handleExternalMessage), pubSub.subscribe(pubSub_topics.pubSubTopics.SEND_FILE_MESSAGE, handleExternalMessage), ]; return [2 /*return*/, function () { subscriptions.forEach(function (subscription) { return subscription.remove(); }); }]; }); }); }, [messageDataSource.initialized, (_b = state.currentChannel) === null || _b === void 0 ? void 0 : _b.url]); // Starting point handling React.useEffect(function () { if (typeof startingPoint === 'number' && messageDataSource.initialized) { actions.scrollToMessage(startingPoint, 0, false, false); } }, [messageDataSource.initialized, startingPoint]); // Animated message handling React.useEffect(function () { if (_animatedMessageId) { actions.setAnimatedMessageId(_animatedMessageId); } }, [_animatedMessageId]); // State update effect var eventHandlers = React.useMemo(function () { return ({ onBeforeSendUserMessage: onBeforeSendUserMessage, onBeforeSendFileMessage: onBeforeSendFileMessage, onBeforeSendVoiceMessage: onBeforeSendVoiceMessage, onBeforeSendMultipleFilesMessage: onBeforeSendMultipleFilesMessage, onBeforeUpdateUserMessage: onBeforeUpdateUserMessage, onBeforeDownloadFileMessage: onBeforeDownloadFileMessage, onBackClick: onBackClick, onChatHeaderActionClick: onChatHeaderActionClick, onReplyInThreadClick: onReplyInThreadClick, onSearchClick: onSearchClick, onQuoteMessageClick: onQuoteMessageClick, onMessageAnimated: onMessageAnimated, }); }, [ onBeforeSendUserMessage, onBeforeSendFileMessage, onBeforeSendVoiceMessage, onBeforeSendMultipleFilesMessage, onBeforeUpdateUserMessage, onBeforeDownloadFileMessage, onBackClick, onChatHeaderActionClick, onReplyInThreadClick, onSearchClick, onQuoteMessageClick, onMessageAnimated, ]); var renderProps = React.useMemo(function () { return ({ renderUserMentionItem: renderUserMentionItem, filterEmojiCategoryIds: filterEmojiCategoryIds, }); }, [renderUserMentionItem, filterEmojiCategoryIds]); var configurations = React.useMemo(function () { return ({ isReactionEnabled: resolvedIsReactionEnabled, isMessageGroupingEnabled: isMessageGroupingEnabled, isMultipleFilesMessageEnabled: isMultipleFilesMessageEnabled, replyType: resolvedReplyType$1, threadReplySelectType: resolvedThreadReplySelectType, showSearchIcon: showSearchIcon !== null && showSearchIcon !== void 0 ? showSearchIcon : config.groupChannelSettings.enableMessageSearch, disableMarkAsRead: disableMarkAsRead, scrollBehavior: scrollBehavior, }); }, [ resolvedIsReactionEnabled, isMessageGroupingEnabled, isMultipleFilesMessageEnabled, resolvedReplyType$1, resolvedThreadReplySelectType, showSearchIcon, disableMarkAsRead, scrollBehavior, config.groupChannelSettings.enableMessageSearch, ]); var scrollState = React.useMemo(function () { return ({ scrollRef: scrollRef, scrollPubSub: scrollPubSub, scrollDistanceFromBottomRef: scrollDistanceFromBottomRef, scrollPositionRef: scrollPositionRef, isScrollBottomReached: isScrollBottomReached, }); }, [ scrollRef, scrollPubSub, scrollDistanceFromBottomRef, scrollPositionRef, isScrollBottomReached, ]); useDeepCompareEffect.useDeepCompareEffect(function () { updateState(_tslib.__assign(_tslib.__assign(_tslib.__assign(_tslib.__assign(_tslib.__assign(_tslib.__assign({ // Channel state channelUrl: channelUrl, currentChannel: state.currentChannel }, configurations), scrollState), eventHandlers), renderProps), messageDataSource), { markAsUnread: markAsUnread, markAsUnreadSourceRef: markAsUnreadSourceRef })); }, [ channelUrl, (_c = state.currentChannel) === null || _c === void 0 ? void 0 : _c.serialize(), configurations, scrollState, eventHandlers, renderProps, messageDataSource.initialized, messageDataSource.loading, messageDataSource.messages.map(function (it) { return it.serialize(); }), ]); return children; }; var GroupChannelProvider = function (props) { return (React__default.default.createElement(InternalGroupChannelProvider, _tslib.__assign({ key: props.channelUrl }, props), React__default.default.createElement(GroupChannelManager, _tslib.__assign({}, props), React__default.default.createElement(UserProfileContext.UserProfileProvider, _tslib.__assign({}, props), props.children)))); }; /** * A specialized hook for GroupChannel state management * @returns {ReturnType<typeof createStore<GroupChannelState>>} */ var useGroupChannelStore = function () { return SendbirdContext.useStore(GroupChannelContext, function (state) { return state; }, initialState()); }; // Keep this function for backward compatibility. var useGroupChannelContext = function () { var _a = useGroupChannel(), state = _a.state, actions = _a.actions; return _tslib.__assign(_tslib.__assign({}, state), actions); }; function getCollectionCreator(groupChannel$1, messageListQueryParams) { return function (defaultParams) { var params = _tslib.__assign(_tslib.__assign(_tslib.__assign({}, defaultParams), { prevResultLimit: 30, nextResultLimit: 30 }), messageListQueryParams); return groupChannel$1.createMessageCollection(_tslib.__assign(_tslib.__assign({}, params), { filter: new groupChannel.MessageFilter(params) })); }; } exports.GroupChannelContext = GroupChannelContext; exports.GroupChannelManager = GroupChannelManager; exports.GroupChannelProvider = GroupChannelProvider; exports.InternalGroupChannelProvider = InternalGroupChannelProvider; exports.useGroupChannel = useGroupChannel; exports.useGroupChannelContext = useGroupChannelContext; //# sourceMappingURL=bundle-C0RMVFg8.js.map