UNPKG

stream-chat-react

Version:

React components to create chat conversations or livestream style chat

674 lines (673 loc) 39 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import React, { useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState, } from 'react'; import debounce from 'lodash.debounce'; import throttle from 'lodash.throttle'; import { logChatPromiseExecution, } from 'stream-chat'; import { nanoid } from 'nanoid'; import { channelReducer, initialState } from './channelState'; import { commonEmoji, defaultMinimalEmojis, emojiSetDef } from './emojiData'; import { useCreateChannelStateContext } from './hooks/useCreateChannelStateContext'; import { useCreateTypingContext } from './hooks/useCreateTypingContext'; import { useEditMessageHandler } from './hooks/useEditMessageHandler'; import { useIsMounted } from './hooks/useIsMounted'; import { useMentionsHandlers } from './hooks/useMentionsHandlers'; import { Attachment as DefaultAttachment } from '../Attachment/Attachment'; import { LoadingErrorIndicator as DefaultLoadingErrorIndicator, } from '../Loading'; import { LoadingChannel as DefaultLoadingIndicator } from './LoadingChannel'; import { MessageSimple } from '../Message/MessageSimple'; import { DropzoneProvider } from '../MessageInput/DropzoneProvider'; import { ChannelActionProvider, } from '../../context/ChannelActionContext'; import { ChannelStateProvider, } from '../../context/ChannelStateContext'; import { ComponentProvider } from '../../context/ComponentContext'; import { useChatContext } from '../../context/ChatContext'; import { EmojiProvider } from '../../context/EmojiContext'; import { useTranslationContext } from '../../context/TranslationContext'; import { TypingProvider } from '../../context/TypingContext'; import { DEFAULT_INITIAL_CHANNEL_PAGE_SIZE, DEFAULT_NEXT_CHANNEL_PAGE_SIZE, DEFAULT_THREAD_PAGE_SIZE, } from '../../constants/limits'; import { hasMoreMessagesProbably, hasNotMoreMessages } from '../MessageList/utils'; import defaultEmojiData from '../../stream-emoji.json'; import { makeAddNotifications } from './utils'; import { useChannelContainerClasses } from './hooks/useChannelContainerClasses'; var UnMemoizedChannel = function (props) { var propsChannel = props.channel, _a = props.EmptyPlaceholder, EmptyPlaceholder = _a === void 0 ? null : _a, LoadingErrorIndicator = props.LoadingErrorIndicator, _b = props.LoadingIndicator, LoadingIndicator = _b === void 0 ? DefaultLoadingIndicator : _b; var _c = useChatContext('Channel'), contextChannel = _c.channel, channelsQueryState = _c.channelsQueryState, customClasses = _c.customClasses, theme = _c.theme; var _d = useChannelContainerClasses({ customClasses: customClasses, }), channelClass = _d.channelClass, chatClass = _d.chatClass; var channel = propsChannel || contextChannel; if (channelsQueryState.queryInProgress === 'reload' && LoadingIndicator) { return (React.createElement("div", { className: "".concat(chatClass, " ").concat(channelClass, " str-chat__channel ").concat(theme) }, React.createElement(LoadingIndicator, null))); } if (channelsQueryState.error && LoadingErrorIndicator) { return (React.createElement("div", { className: "".concat(chatClass, " ").concat(channelClass, " str-chat__channel ").concat(theme) }, React.createElement(LoadingErrorIndicator, { error: channelsQueryState.error }))); } if (!(channel === null || channel === void 0 ? void 0 : channel.cid)) { return (React.createElement("div", { className: "".concat(chatClass, " ").concat(channelClass, " str-chat__channel ").concat(theme) }, EmptyPlaceholder)); } // @ts-ignore return React.createElement(ChannelInner, __assign({}, props, { channel: channel, key: channel.cid })); }; var ChannelInner = function (props) { var _a; var acceptedFiles = props.acceptedFiles, activeUnreadHandler = props.activeUnreadHandler, channel = props.channel, children = props.children, doMarkReadRequest = props.doMarkReadRequest, doSendMessageRequest = props.doSendMessageRequest, doUpdateMessageRequest = props.doUpdateMessageRequest, _b = props.dragAndDropWindow, dragAndDropWindow = _b === void 0 ? false : _b, _c = props.emojiData, emojiData = _c === void 0 ? defaultEmojiData : _c, _d = props.LoadingErrorIndicator, LoadingErrorIndicator = _d === void 0 ? DefaultLoadingErrorIndicator : _d, _e = props.LoadingIndicator, LoadingIndicator = _e === void 0 ? DefaultLoadingIndicator : _e, maxNumberOfFiles = props.maxNumberOfFiles, _f = props.multipleUploads, multipleUploads = _f === void 0 ? true : _f, onMentionsClick = props.onMentionsClick, onMentionsHover = props.onMentionsHover, _g = props.optionalMessageInputProps, optionalMessageInputProps = _g === void 0 ? {} : _g, skipMessageDataMemoization = props.skipMessageDataMemoization; var _h = useChatContext('Channel'), client = _h.client, customClasses = _h.customClasses, latestMessageDatesByChannels = _h.latestMessageDatesByChannels, mutes = _h.mutes, theme = _h.theme; var t = useTranslationContext('Channel').t; var _j = useChannelContainerClasses({ customClasses: customClasses }), channelClass = _j.channelClass, chatClass = _j.chatClass, chatContainerClass = _j.chatContainerClass, windowsEmojiClass = _j.windowsEmojiClass; var _k = useState(channel.getConfig()), channelConfig = _k[0], setChannelConfig = _k[1]; var _l = useState([]), notifications = _l[0], setNotifications = _l[1]; var _m = useState(), quotedMessage = _m[0], setQuotedMessage = _m[1]; var notificationTimeouts = []; var _o = useReducer(channelReducer, __assign(__assign({}, initialState), { loading: !channel.initialized })), state = _o[0], dispatch = _o[1]; var isMounted = useIsMounted(); var originalTitle = useRef(''); var lastRead = useRef(new Date()); var online = useRef(true); var channelCapabilitiesArray = (_a = channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities; var emojiConfig = { commonEmoji: commonEmoji, defaultMinimalEmojis: defaultMinimalEmojis, emojiData: emojiData, emojiSetDef: emojiSetDef, }; var throttledCopyStateFromChannel = throttle(function () { return dispatch({ channel: channel, type: 'copyStateFromChannelOnEvent' }); }, 500, { leading: true, trailing: true, }); var markRead = function () { if (channel.disconnected || !(channelConfig === null || channelConfig === void 0 ? void 0 : channelConfig.read_events)) { return; } lastRead.current = new Date(); if (doMarkReadRequest) { doMarkReadRequest(channel); } else { logChatPromiseExecution(channel.markRead(), 'mark read'); } if (activeUnreadHandler) { activeUnreadHandler(0, originalTitle.current); } else if (originalTitle.current) { document.title = originalTitle.current; } }; var markReadThrottled = throttle(markRead, 500, { leading: true, trailing: true }); var handleEvent = function (event) { var _a, _b, _c, _d, _e, _f, _g, _h; if (event.message) { dispatch({ channel: channel, message: event.message, type: 'updateThreadOnEvent', }); } if (event.type === 'user.watching.start' || event.type === 'user.watching.stop') return; if (event.type === 'typing.start' || event.type === 'typing.stop') { return dispatch({ channel: channel, type: 'setTyping' }); } if (event.type === 'connection.changed' && typeof event.online === 'boolean') { online.current = event.online; } if (event.type === 'message.new') { var mainChannelUpdated = true; if (((_a = event.message) === null || _a === void 0 ? void 0 : _a.parent_id) && !((_b = event.message) === null || _b === void 0 ? void 0 : _b.show_in_channel)) { mainChannelUpdated = false; } if (mainChannelUpdated && ((_d = (_c = event.message) === null || _c === void 0 ? void 0 : _c.user) === null || _d === void 0 ? void 0 : _d.id) !== client.userID) { if (!document.hidden) { markReadThrottled(); } else if ((channelConfig === null || channelConfig === void 0 ? void 0 : channelConfig.read_events) && !channel.muteStatus().muted) { var unread = channel.countUnread(lastRead.current); if (activeUnreadHandler) { activeUnreadHandler(unread, originalTitle.current); } else { document.title = "(".concat(unread, ") ").concat(originalTitle.current); } } } if (((_f = (_e = event.message) === null || _e === void 0 ? void 0 : _e.user) === null || _f === void 0 ? void 0 : _f.id) === client.userID && ((_g = event === null || event === void 0 ? void 0 : event.message) === null || _g === void 0 ? void 0 : _g.created_at) && ((_h = event === null || event === void 0 ? void 0 : event.message) === null || _h === void 0 ? void 0 : _h.cid)) { var messageDate = new Date(event.message.created_at); var cid = event.message.cid; if (!latestMessageDatesByChannels[cid] || latestMessageDatesByChannels[cid].getTime() < messageDate.getTime()) { latestMessageDatesByChannels[cid] = messageDate; } } } throttledCopyStateFromChannel(); }; // useLayoutEffect here to prevent spinner. Use Suspense when it is available in stable release useLayoutEffect(function () { var errored = false; var done = false; var onVisibilityChange = function () { if (!document.hidden) markRead(); }; (function () { return __awaiter(void 0, void 0, void 0, function () { var config, e_1; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!!channel.initialized) return [3 /*break*/, 4]; _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, channel.watch()]; case 2: _a.sent(); config = channel.getConfig(); setChannelConfig(config); return [3 /*break*/, 4]; case 3: e_1 = _a.sent(); dispatch({ error: e_1, type: 'setError' }); errored = true; return [3 /*break*/, 4]; case 4: done = true; originalTitle.current = document.title; if (!errored) { dispatch({ channel: channel, type: 'initStateFromChannel' }); if (channel.countUnread() > 0) markRead(); // The more complex sync logic is done in Chat document.addEventListener('visibilitychange', onVisibilityChange); client.on('connection.changed', handleEvent); client.on('connection.recovered', handleEvent); client.on('user.updated', handleEvent); client.on('user.deleted', handleEvent); channel.on(handleEvent); } return [2 /*return*/]; } }); }); })(); return function () { if (errored || !done) return; document.removeEventListener('visibilitychange', onVisibilityChange); channel === null || channel === void 0 ? void 0 : channel.off(handleEvent); client.off('connection.changed', handleEvent); client.off('connection.recovered', handleEvent); client.off('user.updated', handleEvent); client.off('user.deleted', handleEvent); notificationTimeouts.forEach(clearTimeout); }; }, [channel.cid, doMarkReadRequest]); useEffect(function () { var _a; if (!state.thread) return; var message = (_a = state.messages) === null || _a === void 0 ? void 0 : _a.find(function (m) { var _a; return m.id === ((_a = state.thread) === null || _a === void 0 ? void 0 : _a.id); }); if (message) dispatch({ message: message, type: 'setThread' }); }, [state.messages, state.thread]); /** MESSAGE */ // Adds a temporary notification to message list, will be removed after 5 seconds var addNotification = makeAddNotifications(setNotifications, notificationTimeouts); var loadMoreFinished = debounce(function (hasMore, messages) { if (!isMounted.current) return; dispatch({ hasMore: hasMore, messages: messages, type: 'loadMoreFinished' }); }, 2000, { leading: true, trailing: true, }); var loadMore = function (limit) { if (limit === void 0) { limit = DEFAULT_NEXT_CHANNEL_PAGE_SIZE; } return __awaiter(void 0, void 0, void 0, function () { var oldestMessage, notHasMore, oldestID, perPage, queryResponse, e_2, hasMoreMessages; var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!online.current || !window.navigator.onLine) return [2 /*return*/, 0]; oldestMessage = (_a = state === null || state === void 0 ? void 0 : state.messages) === null || _a === void 0 ? void 0 : _a[0]; if (state.loadingMore || state.loadingMoreNewer || (oldestMessage === null || oldestMessage === void 0 ? void 0 : oldestMessage.status) !== 'received') { return [2 /*return*/, 0]; } notHasMore = hasNotMoreMessages(channel.state.messages.length, DEFAULT_INITIAL_CHANNEL_PAGE_SIZE); if (notHasMore) { loadMoreFinished(false, channel.state.messages); return [2 /*return*/, channel.state.messages.length]; } dispatch({ loadingMore: true, type: 'setLoadingMore' }); oldestID = oldestMessage === null || oldestMessage === void 0 ? void 0 : oldestMessage.id; perPage = limit; _b.label = 1; case 1: _b.trys.push([1, 3, , 4]); return [4 /*yield*/, channel.query({ messages: { id_lt: oldestID, limit: perPage }, watchers: { limit: perPage }, })]; case 2: queryResponse = _b.sent(); return [3 /*break*/, 4]; case 3: e_2 = _b.sent(); console.warn('message pagination request failed with error', e_2); dispatch({ loadingMore: false, type: 'setLoadingMore' }); return [2 /*return*/, 0]; case 4: hasMoreMessages = queryResponse.messages.length === perPage; loadMoreFinished(hasMoreMessages, channel.state.messages); return [2 /*return*/, queryResponse.messages.length]; } }); }); }; var loadMoreNewer = function (limit) { if (limit === void 0) { limit = 100; } return __awaiter(void 0, void 0, void 0, function () { var newestMessage, newestId, perPage, queryResponse, e_3, hasMoreNewer; var _a, _b; return __generator(this, function (_c) { switch (_c.label) { case 0: if (!online.current || !window.navigator.onLine) return [2 /*return*/, 0]; newestMessage = (_a = state === null || state === void 0 ? void 0 : state.messages) === null || _a === void 0 ? void 0 : _a[((_b = state === null || state === void 0 ? void 0 : state.messages) === null || _b === void 0 ? void 0 : _b.length) - 1]; if (state.loadingMore || state.loadingMoreNewer) return [2 /*return*/, 0]; dispatch({ loadingMoreNewer: true, type: 'setLoadingMoreNewer' }); newestId = newestMessage === null || newestMessage === void 0 ? void 0 : newestMessage.id; perPage = limit; _c.label = 1; case 1: _c.trys.push([1, 3, , 4]); return [4 /*yield*/, channel.query({ messages: { id_gt: newestId, limit: perPage }, watchers: { limit: perPage }, })]; case 2: queryResponse = _c.sent(); return [3 /*break*/, 4]; case 3: e_3 = _c.sent(); console.warn('message pagination request failed with error', e_3); dispatch({ loadingMoreNewer: false, type: 'setLoadingMoreNewer' }); return [2 /*return*/, 0]; case 4: hasMoreNewer = channel.state.messages !== channel.state.latestMessages; dispatch({ hasMoreNewer: hasMoreNewer, messages: channel.state.messages, type: 'loadMoreNewerFinished' }); return [2 /*return*/, queryResponse.messages.length]; } }); }); }; var clearHighlightedMessageTimeoutId = useRef(null); var jumpToMessage = function (messageId, messageLimit) { if (messageLimit === void 0) { messageLimit = 100; } return __awaiter(void 0, void 0, void 0, function () { var indexOfMessage, hasMoreMessages; return __generator(this, function (_a) { switch (_a.label) { case 0: dispatch({ loadingMore: true, type: 'setLoadingMore' }); return [4 /*yield*/, channel.state.loadMessageIntoState(messageId, undefined, messageLimit)]; case 1: _a.sent(); indexOfMessage = channel.state.messages.findIndex(function (message) { return message.id === messageId; }); hasMoreMessages = indexOfMessage >= Math.floor(messageLimit / 2); loadMoreFinished(hasMoreMessages, channel.state.messages); dispatch({ hasMoreNewer: channel.state.messages !== channel.state.latestMessages, highlightedMessageId: messageId, type: 'jumpToMessageFinished', }); if (clearHighlightedMessageTimeoutId.current) { clearTimeout(clearHighlightedMessageTimeoutId.current); } clearHighlightedMessageTimeoutId.current = setTimeout(function () { clearHighlightedMessageTimeoutId.current = null; dispatch({ type: 'clearHighlightedMessage' }); }, 500); return [2 /*return*/]; } }); }); }; var jumpToLatestMessage = function () { return __awaiter(void 0, void 0, void 0, function () { var hasMoreOlder; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, channel.state.loadMessageIntoState('latest')]; case 1: _a.sent(); hasMoreOlder = channel.state.messages.length >= 25; loadMoreFinished(hasMoreOlder, channel.state.messages); dispatch({ type: 'jumpToLatestMessage', }); return [2 /*return*/]; } }); }); }; var updateMessage = function (updatedMessage) { // add the message to the local channel state channel.state.addMessageSorted(updatedMessage, true); dispatch({ channel: channel, parentId: state.thread && updatedMessage.parent_id, type: 'copyMessagesFromChannel', }); }; var isUserResponseArray = function (output) { var _a; return ((_a = output[0]) === null || _a === void 0 ? void 0 : _a.id) != null; }; var doSendMessage = function (message, customMessageData) { return __awaiter(void 0, void 0, void 0, function () { var attachments, id, _a, mentioned_users, parent_id, text, mentions, messageData, messageResponse, error_1, stringError, parsedError; return __generator(this, function (_b) { switch (_b.label) { case 0: attachments = message.attachments, id = message.id, _a = message.mentioned_users, mentioned_users = _a === void 0 ? [] : _a, parent_id = message.parent_id, text = message.text; mentions = isUserResponseArray(mentioned_users) ? mentioned_users.map(function (_a) { var id = _a.id; return id; }) : mentioned_users; messageData = __assign({ attachments: attachments, id: id, mentioned_users: mentions, parent_id: parent_id, quoted_message_id: parent_id === (quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.parent_id) ? quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.id : undefined, text: text }, customMessageData); _b.label = 1; case 1: _b.trys.push([1, 6, , 7]); messageResponse = void 0; if (!doSendMessageRequest) return [3 /*break*/, 3]; return [4 /*yield*/, doSendMessageRequest(channel.cid, messageData)]; case 2: messageResponse = _b.sent(); return [3 /*break*/, 5]; case 3: return [4 /*yield*/, channel.sendMessage(messageData)]; case 4: messageResponse = _b.sent(); _b.label = 5; case 5: // replace it after send is completed if (messageResponse === null || messageResponse === void 0 ? void 0 : messageResponse.message) { updateMessage(__assign(__assign({}, messageResponse.message), { status: 'received' })); } if (quotedMessage && parent_id === (quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.parent_id)) setQuotedMessage(undefined); return [3 /*break*/, 7]; case 6: error_1 = _b.sent(); stringError = JSON.stringify(error_1); parsedError = stringError ? JSON.parse(stringError) : {}; updateMessage(__assign(__assign({}, message), { error: parsedError, errorStatusCode: parsedError.status || undefined, status: 'failed' })); return [3 /*break*/, 7]; case 7: return [2 /*return*/]; } }); }); }; var sendMessage = function (_a, customMessageData) { var _b = _a.attachments, attachments = _b === void 0 ? [] : _b, _c = _a.mentioned_users, mentioned_users = _c === void 0 ? [] : _c, parent = _a.parent, _d = _a.text, text = _d === void 0 ? '' : _d; return __awaiter(void 0, void 0, void 0, function () { var messagePreview; var _e; return __generator(this, function (_f) { switch (_f.label) { case 0: channel.state.filterErrorMessages(); messagePreview = __assign({ __html: text, attachments: attachments, created_at: new Date(), html: text, id: (_e = customMessageData === null || customMessageData === void 0 ? void 0 : customMessageData.id) !== null && _e !== void 0 ? _e : "".concat(client.userID, "-").concat(nanoid()), mentioned_users: mentioned_users, reactions: [], status: 'sending', text: text, type: 'regular', user: client.user }, ((parent === null || parent === void 0 ? void 0 : parent.id) ? { parent_id: parent.id } : null)); updateMessage(messagePreview); return [4 /*yield*/, doSendMessage(messagePreview, customMessageData)]; case 1: _f.sent(); return [2 /*return*/]; } }); }); }; var retrySendMessage = function (message) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: updateMessage(__assign(__assign({}, message), { errorStatusCode: undefined, status: 'sending' })); return [4 /*yield*/, doSendMessage(message)]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; var removeMessage = function (message) { channel.state.removeMessage(message); dispatch({ channel: channel, parentId: state.thread && message.parent_id, type: 'copyMessagesFromChannel', }); }; /** THREAD */ var openThread = function (message, event) { event.preventDefault(); setQuotedMessage(function (current) { if ((current === null || current === void 0 ? void 0 : current.parent_id) !== (message === null || message === void 0 ? void 0 : message.parent_id)) { return undefined; } else { return current; } }); dispatch({ channel: channel, message: message, type: 'openThread' }); }; var closeThread = function (event) { event.preventDefault(); dispatch({ type: 'closeThread' }); }; var loadMoreThreadFinished = debounce(function (threadHasMore, threadMessages) { dispatch({ threadHasMore: threadHasMore, threadMessages: threadMessages, type: 'loadMoreThreadFinished', }); }, 2000, { leading: true, trailing: true }); var loadMoreThread = function (limit) { if (limit === void 0) { limit = DEFAULT_THREAD_PAGE_SIZE; } return __awaiter(void 0, void 0, void 0, function () { var parentID, oldMessages, oldestMessageID, queryResponse, threadHasMoreMessages, newThreadMessages, e_4; var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: if (state.threadLoadingMore || !state.thread) return [2 /*return*/]; dispatch({ type: 'startLoadingThread' }); parentID = state.thread.id; if (!parentID) { return [2 /*return*/, dispatch({ type: 'closeThread' })]; } oldMessages = channel.state.threads[parentID] || []; oldestMessageID = (_a = oldMessages[0]) === null || _a === void 0 ? void 0 : _a.id; _b.label = 1; case 1: _b.trys.push([1, 3, , 4]); return [4 /*yield*/, channel.getReplies(parentID, { id_lt: oldestMessageID, limit: limit, })]; case 2: queryResponse = _b.sent(); threadHasMoreMessages = hasMoreMessagesProbably(queryResponse.messages.length, limit); newThreadMessages = channel.state.threads[parentID] || []; // next set loadingMore to false so we can start asking for more data loadMoreThreadFinished(threadHasMoreMessages, newThreadMessages); return [3 /*break*/, 4]; case 3: e_4 = _b.sent(); loadMoreThreadFinished(false, oldMessages); return [3 /*break*/, 4]; case 4: return [2 /*return*/]; } }); }); }; var onMentionsHoverOrClick = useMentionsHandlers(onMentionsHover, onMentionsClick); var editMessage = useEditMessageHandler(doUpdateMessageRequest); var typing = state.typing, restState = __rest(state, ["typing"]); var channelStateContextValue = useCreateChannelStateContext(__assign(__assign({}, restState), { acceptedFiles: acceptedFiles, channel: channel, channelCapabilitiesArray: channelCapabilitiesArray, channelConfig: channelConfig, dragAndDropWindow: dragAndDropWindow, giphyVersion: props.giphyVersion || 'fixed_height', maxNumberOfFiles: maxNumberOfFiles, multipleUploads: multipleUploads, mutes: mutes, notifications: notifications, quotedMessage: quotedMessage, watcher_count: state.watcherCount })); var channelActionContextValue = useMemo(function () { return ({ addNotification: addNotification, closeThread: closeThread, dispatch: dispatch, editMessage: editMessage, jumpToLatestMessage: jumpToLatestMessage, jumpToMessage: jumpToMessage, loadMore: loadMore, loadMoreNewer: loadMoreNewer, loadMoreThread: loadMoreThread, onMentionsClick: onMentionsHoverOrClick, onMentionsHover: onMentionsHoverOrClick, openThread: openThread, removeMessage: removeMessage, retrySendMessage: retrySendMessage, sendMessage: sendMessage, setQuotedMessage: setQuotedMessage, skipMessageDataMemoization: skipMessageDataMemoization, updateMessage: updateMessage, }); }, [channel.cid, loadMore, loadMoreNewer, quotedMessage, jumpToMessage, jumpToLatestMessage]); var componentContextValue = useMemo(function () { return ({ Attachment: props.Attachment || DefaultAttachment, AutocompleteSuggestionHeader: props.AutocompleteSuggestionHeader, AutocompleteSuggestionItem: props.AutocompleteSuggestionItem, AutocompleteSuggestionList: props.AutocompleteSuggestionList, Avatar: props.Avatar, CooldownTimer: props.CooldownTimer, DateSeparator: props.DateSeparator, EditMessageInput: props.EditMessageInput, EmojiIcon: props.EmojiIcon, EmptyStateIndicator: props.EmptyStateIndicator, FileUploadIcon: props.FileUploadIcon, GiphyPreviewMessage: props.GiphyPreviewMessage, HeaderComponent: props.HeaderComponent, Input: props.Input, LoadingIndicator: props.LoadingIndicator, Message: props.Message || MessageSimple, MessageDeleted: props.MessageDeleted, MessageListNotifications: props.MessageListNotifications, MessageNotification: props.MessageNotification, MessageOptions: props.MessageOptions, MessageRepliesCountButton: props.MessageRepliesCountButton, MessageStatus: props.MessageStatus, MessageSystem: props.MessageSystem, MessageTimestamp: props.MessageTimestamp, ModalGallery: props.ModalGallery, PinIndicator: props.PinIndicator, QuotedMessage: props.QuotedMessage, QuotedMessagePreview: props.QuotedMessagePreview, ReactionSelector: props.ReactionSelector, ReactionsList: props.ReactionsList, SendButton: props.SendButton, ThreadHead: props.ThreadHead, ThreadHeader: props.ThreadHeader, ThreadStart: props.ThreadStart, TriggerProvider: props.TriggerProvider, TypingIndicator: props.TypingIndicator, VirtualMessage: props.VirtualMessage, }); }, []); var emojiContextValue = useMemo(function () { return ({ Emoji: props.Emoji, emojiConfig: emojiConfig, EmojiIndex: props.EmojiIndex, EmojiPicker: props.EmojiPicker, }); }, []); var typingContextValue = useCreateTypingContext({ typing: typing, }); var OptionalMessageInputProvider = useMemo(function () { return (dragAndDropWindow ? DropzoneProvider : React.Fragment); }, [dragAndDropWindow]); if (state.error) { return (React.createElement("div", { className: "".concat(chatClass, " ").concat(channelClass, " str-chat__channel ").concat(theme) }, React.createElement(LoadingErrorIndicator, { error: state.error }))); } if (state.loading) { return (React.createElement("div", { className: "".concat(chatClass, " ").concat(channelClass, " str-chat__channel ").concat(theme) }, React.createElement(LoadingIndicator, null))); } if (!channel.watch) { return (React.createElement("div", { className: "".concat(chatClass, " ").concat(channelClass, " str-chat__channel ").concat(theme) }, React.createElement("div", null, t('Channel Missing')))); } return (React.createElement("div", { className: "".concat(chatClass, " ").concat(channelClass, " str-chat__channel ").concat(theme, " ").concat(windowsEmojiClass) }, React.createElement(ChannelStateProvider, { value: channelStateContextValue }, React.createElement(ChannelActionProvider, { value: channelActionContextValue }, React.createElement(ComponentProvider, { value: componentContextValue }, React.createElement(EmojiProvider, { value: emojiContextValue }, React.createElement(TypingProvider, { value: typingContextValue }, React.createElement("div", { className: "".concat(chatContainerClass) }, React.createElement(OptionalMessageInputProvider, __assign({}, optionalMessageInputProps), children))))))))); }; /** * A wrapper component that provides channel data and renders children. * The Channel component provides the following contexts: * - [ChannelStateContext](https://getstream.io/chat/docs/sdk/react/contexts/channel_state_context/) * - [ChannelActionContext](https://getstream.io/chat/docs/sdk/react/contexts/channel_action_context/) * - [ComponentContext](https://getstream.io/chat/docs/sdk/react/contexts/component_context/) * - [EmojiContext](https://getstream.io/chat/docs/sdk/react/contexts/emoji_context/) * - [TypingContext](https://getstream.io/chat/docs/sdk/react/contexts/typing_context/) */ export var Channel = React.memo(UnMemoizedChannel);