import React__default, { useEffect, useCallback, useRef, useState, useReducer, useMemo } from 'react';
import { U as UserProfileProvider } from './UserProfileContext-d5787c95.js';
import useSendbirdStateContext from './useSendbirdStateContext.js';
import { N as NEXT_RESULT_SIZE, P as PREV_RESULT_SIZE, T as ThreadReplySelectType } from './const-97fac210.js';
import { f as format } from './index-2dc53ac2.js';
import { P as PUBSUB_TOPICS } from './topics-f3629ea0.js';
import { a as getSendingMessageStatus, b as isReadMessage, c as filterMessageListParams } from './index-eefb44ba.js';
import { _ as _objectSpread2 } from './_rollupPluginBabelHelpers-4f8ebde4.js';
import { c as compareIds } from './compareIds-7800035f.js';
import { GroupChannelHandler } from '@sendbird/chat/groupChannel';
import { u as uuidv4 } from './uuid-a79b5ba8.js';
import { ReplyType, MessageMetaArray } from '@sendbird/chat/message';
import { b as VOICE_MESSAGE_FILE_NAME, c as VOICE_MESSAGE_MIME_TYPE, M as META_ARRAY_VOICE_DURATION_KEY, d as META_ARRAY_MESSAGE_TYPE_KEY, e as META_ARRAY_MESSAGE_TYPE_VALUE__VOICE } from './consts-33537265.js';
import { a as getCaseResolvedThreadReplySelectType } from './resolvedReplyType-e00d5fd9.js';

const RESET_MESSAGES = 'RESET_MESSAGES';
const FETCH_INITIAL_MESSAGES_START = 'FETCH_INITIAL_MESSAGES_START';
const FETCH_INITIAL_MESSAGES_SUCCESS = 'FETCH_INITIAL_MESSAGES_SUCCESS';
const FETCH_INITIAL_MESSAGES_FAILURE = 'FETCH_INITIAL_MESSAGES_FAILURE';
const FETCH_PREV_MESSAGES_SUCCESS = 'FETCH_PREV_MESSAGES_SUCCESS';
const FETCH_PREV_MESSAGES_FAILURE = 'FETCH_PREV_MESSAGES_FAILURE';
const FETCH_NEXT_MESSAGES_SUCCESS = 'FETCH_NEXT_MESSAGES_SUCCESS';
const FETCH_NEXT_MESSAGES_FAILURE = 'FETCH_NEXT_MESSAGES_FAILURE';
const SEND_MESSAGEGE_START = 'SEND_MESSAGEGE_START';
const SEND_MESSAGEGE_SUCESS = 'SEND_MESSAGEGE_SUCESS';
const SEND_MESSAGEGE_FAILURE = 'SEND_MESSAGEGE_FAILURE';
const RESEND_MESSAGEGE_START = 'RESEND_MESSAGEGE_START';
const ON_MESSAGE_RECEIVED = 'ON_MESSAGE_RECEIVED';
const ON_MESSAGE_UPDATED = 'ON_MESSAGE_UPDATED';
const ON_MESSAGE_THREAD_INFO_UPDATED = 'ON_MESSAGE_THREAD_INFO_UPDATED';
const ON_MESSAGE_DELETED = 'ON_MESSAGE_DELETED';
const ON_MESSAGE_DELETED_BY_REQ_ID = 'ON_MESSAGE_DELETED_BY_REQ_ID';
const SET_CURRENT_CHANNEL = 'SET_CURRENT_CHANNEL';
const SET_CHANNEL_INVALID = 'SET_CHANNEL_INVALID';
const MARK_AS_READ = 'MARK_AS_READ';
const ON_REACTION_UPDATED = 'ON_REACTION_UPDATED';
const SET_EMOJI_CONTAINER = 'SET_EMOJI_CONTAINER';
const MESSAGE_LIST_PARAMS_CHANGED = 'MESSAGE_LIST_PARAMS_CHANGED';

var messageActionTypes = /*#__PURE__*/Object.freeze({
  __proto__: null,
  RESET_MESSAGES: RESET_MESSAGES,
  FETCH_INITIAL_MESSAGES_START: FETCH_INITIAL_MESSAGES_START,
  FETCH_INITIAL_MESSAGES_SUCCESS: FETCH_INITIAL_MESSAGES_SUCCESS,
  FETCH_INITIAL_MESSAGES_FAILURE: FETCH_INITIAL_MESSAGES_FAILURE,
  FETCH_PREV_MESSAGES_SUCCESS: FETCH_PREV_MESSAGES_SUCCESS,
  FETCH_PREV_MESSAGES_FAILURE: FETCH_PREV_MESSAGES_FAILURE,
  FETCH_NEXT_MESSAGES_SUCCESS: FETCH_NEXT_MESSAGES_SUCCESS,
  FETCH_NEXT_MESSAGES_FAILURE: FETCH_NEXT_MESSAGES_FAILURE,
  SEND_MESSAGEGE_START: SEND_MESSAGEGE_START,
  SEND_MESSAGEGE_SUCESS: SEND_MESSAGEGE_SUCESS,
  SEND_MESSAGEGE_FAILURE: SEND_MESSAGEGE_FAILURE,
  RESEND_MESSAGEGE_START: RESEND_MESSAGEGE_START,
  ON_MESSAGE_RECEIVED: ON_MESSAGE_RECEIVED,
  ON_MESSAGE_UPDATED: ON_MESSAGE_UPDATED,
  ON_MESSAGE_THREAD_INFO_UPDATED: ON_MESSAGE_THREAD_INFO_UPDATED,
  ON_MESSAGE_DELETED: ON_MESSAGE_DELETED,
  ON_MESSAGE_DELETED_BY_REQ_ID: ON_MESSAGE_DELETED_BY_REQ_ID,
  SET_CURRENT_CHANNEL: SET_CURRENT_CHANNEL,
  SET_CHANNEL_INVALID: SET_CHANNEL_INVALID,
  MARK_AS_READ: MARK_AS_READ,
  ON_REACTION_UPDATED: ON_REACTION_UPDATED,
  SET_EMOJI_CONTAINER: SET_EMOJI_CONTAINER,
  MESSAGE_LIST_PARAMS_CHANGED: MESSAGE_LIST_PARAMS_CHANGED
});

const UNDEFINED = 'undefined';
const {
  SUCCEEDED: SUCCEEDED$1,
  FAILED,
  PENDING
} = getSendingMessageStatus();
const scrollToRenderedMessage = (scrollRef, initialTimeStamp) => {
  try {
    var _container$querySelec;
    const container = scrollRef.current;
    // scroll into the message with initialTimeStamp
    const element = (_container$querySelec = container.querySelectorAll(`[data-sb-created-at="${initialTimeStamp}"]`)) === null || _container$querySelec === void 0 ? void 0 : _container$querySelec[0];
    if (element) {
      // Calculate the offset of the element from the top of the container
      const containerHeight = container.offsetHeight;
      const elementHeight = element.offsetHeight;
      const elementOffset = (containerHeight - elementHeight) / 2;
      // Set the scroll position of the container to bring the element to the middle
      container.scrollTop = element.offsetTop - elementOffset;
    }
  } catch (_unused) {
    // do nothing
  }
};

/* eslint-disable default-param-last */
const scrollIntoLast = function () {
  let initialTry = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
  let scrollRef = arguments.length > 1 ? arguments[1] : undefined;
  const MAX_TRIES = 10;
  const currentTry = initialTry;
  if (currentTry > MAX_TRIES) {
    return;
  }
  try {
    const scrollDOM = (scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current) || document.querySelector('.sendbird-conversation__messages-padding');
    // eslint-disable-next-line no-multi-assign
    scrollDOM.scrollTop = scrollDOM.scrollHeight;
  } catch (error) {
    setTimeout(() => {
      scrollIntoLast(currentTry + 1, scrollRef);
    }, 500 * currentTry);
  }
};
const pubSubHandleRemover = subscriber => {
  subscriber.forEach(s => {
    try {
      s.remove();
    } catch (_unused2) {
      //
    }
  });
};
const pubSubHandler = _ref => {
  let {
    channelUrl,
    pubSub,
    dispatcher,
    scrollRef
  } = _ref;
  const subscriber = new Map();
  if (!pubSub || !pubSub.subscribe) return subscriber;
  subscriber.set(PUBSUB_TOPICS.SEND_USER_MESSAGE, pubSub.subscribe(PUBSUB_TOPICS.SEND_USER_MESSAGE, msg => {
    const {
      channel,
      message
    } = msg;
    scrollIntoLast(0, scrollRef);
    if (channelUrl === (channel === null || channel === void 0 ? void 0 : channel.url)) {
      dispatcher({
        type: SEND_MESSAGEGE_SUCESS,
        payload: message
      });
    }
  }));
  subscriber.set(PUBSUB_TOPICS.SEND_MESSAGE_START, pubSub.subscribe(PUBSUB_TOPICS.SEND_MESSAGE_START, msg => {
    const {
      channel,
      message
    } = msg;
    if (channelUrl === (channel === null || channel === void 0 ? void 0 : channel.url)) {
      dispatcher({
        type: SEND_MESSAGEGE_START,
        payload: message
      });
    }
  }));
  subscriber.set(PUBSUB_TOPICS.SEND_FILE_MESSAGE, pubSub.subscribe(PUBSUB_TOPICS.SEND_FILE_MESSAGE, msg => {
    const {
      channel,
      message
    } = msg;
    scrollIntoLast(0, scrollRef);
    if (channelUrl === (channel === null || channel === void 0 ? void 0 : channel.url)) {
      dispatcher({
        type: SEND_MESSAGEGE_SUCESS,
        payload: message
      });
    }
  }));
  subscriber.set(PUBSUB_TOPICS.UPDATE_USER_MESSAGE, pubSub.subscribe(PUBSUB_TOPICS.UPDATE_USER_MESSAGE, msg => {
    const {
      channel,
      message,
      fromSelector
    } = msg;
    if (fromSelector && channelUrl === (channel === null || channel === void 0 ? void 0 : channel.url)) {
      dispatcher({
        type: ON_MESSAGE_UPDATED,
        payload: {
          channel,
          message
        }
      });
    }
  }));
  subscriber.set(PUBSUB_TOPICS.DELETE_MESSAGE, pubSub.subscribe(PUBSUB_TOPICS.DELETE_MESSAGE, msg => {
    const {
      channel,
      messageId
    } = msg;
    if (channelUrl === (channel === null || channel === void 0 ? void 0 : channel.url)) {
      dispatcher({
        type: ON_MESSAGE_DELETED,
        payload: messageId
      });
    }
  }));
  return subscriber;
};
const isOperator = function () {
  let groupChannel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  const myRole = groupChannel === null || groupChannel === void 0 ? void 0 : groupChannel.myRole;
  return myRole === 'operator';
};
const isDisabledBecauseFrozen = function () {
  let groupChannel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  const isFrozen = groupChannel === null || groupChannel === void 0 ? void 0 : groupChannel.isFrozen;
  return isFrozen && !isOperator(groupChannel);
};
const isDisabledBecauseMuted = function () {
  let groupChannel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  const myMutedState = groupChannel === null || groupChannel === void 0 ? void 0 : groupChannel.myMutedState;
  return myMutedState === 'muted';
};
const getAllEmojisMapFromEmojiContainer = function () {
  let emojiContainer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  const {
    emojiCategories = []
  } = emojiContainer;
  const allEmojisMap = new Map();
  for (let categoryIndex = 0; categoryIndex < emojiCategories.length; categoryIndex += 1) {
    const {
      emojis
    } = emojiCategories[categoryIndex];
    for (let emojiIndex = 0; emojiIndex < emojis.length; emojiIndex += 1) {
      const {
        key,
        url
      } = emojis[emojiIndex];
      allEmojisMap.set(key, url);
    }
  }
  return allEmojisMap;
};
const getNicknamesMapFromMembers = function () {
  let members = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  const nicknamesMap = new Map();
  for (let memberIndex = 0; memberIndex < members.length; memberIndex += 1) {
    const {
      userId,
      nickname
    } = members[memberIndex];
    nicknamesMap.set(userId, nickname);
  }
  return nicknamesMap;
};
const getUniqueListBy = (arr, key) => [...new Map(arr.map(item => [item[key], item])).values()];
const getUniqueListByMessageId = arr => getUniqueListBy(arr, 'messageId');
const sortByCreatedAt = messages => messages.sort((a, b) => a.createdAt - b.createdAt);
const mergeAndSortMessages = (oldMessages, newMessages) => {
  const lastOldMessage = oldMessages[oldMessages.length - 1];
  const firstNewMessage = newMessages[0];
  // If the last message of oldMessages is older than the first message of newMessages,
  // then we can safely append newMessages to oldMessages.
  if ((lastOldMessage === null || lastOldMessage === void 0 ? void 0 : lastOldMessage.createdAt) < (firstNewMessage === null || firstNewMessage === void 0 ? void 0 : firstNewMessage.createdAt)) {
    return [...oldMessages, ...newMessages];
  }

  // todo: optimize this
  // If the last message of oldMessages is newer than the first message of newMessages,
  // then we need to merge the two arrays and sort them by createdAt.
  const mergedMessages = [...oldMessages, ...newMessages];
  const unique = getUniqueListByMessageId(mergedMessages);
  return sortByCreatedAt(unique);
};
const getMessageCreatedAt = message => format(message.createdAt, 'p');
const isSameGroup = (message, comparingMessage, currentChannel) => {
  var _message$sender, _comparingMessage$sen, _message$sender2, _comparingMessage$sen2;
  if (!(message && comparingMessage && message.messageType && message.messageType !== 'admin' && comparingMessage.messageType && (comparingMessage === null || comparingMessage === void 0 ? void 0 : comparingMessage.messageType) !== 'admin' && message !== null && message !== void 0 && message.sender && comparingMessage !== null && comparingMessage !== void 0 && comparingMessage.sender && message !== null && message !== void 0 && message.createdAt && comparingMessage !== null && comparingMessage !== void 0 && comparingMessage.createdAt && message !== null && message !== void 0 && (_message$sender = message.sender) !== null && _message$sender !== void 0 && _message$sender.userId && comparingMessage !== null && comparingMessage !== void 0 && (_comparingMessage$sen = comparingMessage.sender) !== null && _comparingMessage$sen !== void 0 && _comparingMessage$sen.userId)) {
    return false;
  }
  return (message === null || message === void 0 ? void 0 : message.sendingStatus) === (comparingMessage === null || comparingMessage === void 0 ? void 0 : comparingMessage.sendingStatus) && (message === null || message === void 0 ? void 0 : (_message$sender2 = message.sender) === null || _message$sender2 === void 0 ? void 0 : _message$sender2.userId) === (comparingMessage === null || comparingMessage === void 0 ? void 0 : (_comparingMessage$sen2 = comparingMessage.sender) === null || _comparingMessage$sen2 === void 0 ? void 0 : _comparingMessage$sen2.userId) && getMessageCreatedAt(message) === getMessageCreatedAt(comparingMessage) && isReadMessage(currentChannel, message) === isReadMessage(currentChannel, comparingMessage);
};
const compareMessagesForGrouping = (prevMessage, currMessage, nextMessage, currentChannel, replyType) => {
  if (replyType === 'THREAD' && currMessage !== null && currMessage !== void 0 && currMessage.threadInfo) {
    return [false, false];
  }
  const sendingStatus = (currMessage === null || currMessage === void 0 ? void 0 : currMessage.sendingStatus) || '';
  const isAcceptable = sendingStatus !== 'pending' && sendingStatus !== 'failed';
  return [isSameGroup(prevMessage, currMessage, currentChannel) && isAcceptable, isSameGroup(currMessage, nextMessage, currentChannel) && isAcceptable];
};
const passUnsuccessfullMessages = (allMessages, newMessage) => {
  const {
    sendingStatus = UNDEFINED
  } = newMessage;
  if (sendingStatus === SUCCEEDED$1 || sendingStatus === PENDING) {
    const lastIndexOfSucceededMessage = allMessages.map(message => message.sendingStatus || (message.isAdminMessage && message.isAdminMessage() ? SUCCEEDED$1 : UNDEFINED)).lastIndexOf(SUCCEEDED$1);
    if (lastIndexOfSucceededMessage + 1 < allMessages.length) {
      const messages = [...allMessages];
      messages.splice(lastIndexOfSucceededMessage + 1, 0, newMessage);
      return messages;
    }
  }
  return [...allMessages, newMessage];
};
const pxToNumber = px => {
  if (typeof px === 'number') {
    return px;
  }
  if (typeof px === 'string') {
    const parsed = Number.parseFloat(px);
    if (!Number.isNaN(parsed)) {
      return parsed;
    }
  }
  return null;
};
const isAboutSame = (a, b, px) => Math.abs(a - b) <= px;

/**
 * This function helps consider the every condition
 * related to enabling emoji reaction feature.
 */

function getIsReactionEnabled(_ref) {
  let {
    isBroadcast = false,
    isSuper = false,
    globalLevel = true,
    moduleLevel
  } = _ref;
  return !(isBroadcast || isSuper) && (moduleLevel !== null && moduleLevel !== void 0 ? moduleLevel : globalLevel);
}

var messagesInitialState = {
  initialized: false,
  loading: true,
  allMessages: [],
  currentGroupChannel: {
    members: []
  },
  // 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: {},
  unreadSince: null,
  /**
   * unreadSince is a formatted date information string
   * It's used only for the {unreadSince && <UnreadCount time={unreadSince} />}
   */
  isInvalid: false,
  messageListParams: null
};

const {
  SUCCEEDED
} = getSendingMessageStatus();
const getOldestMessageTimeStamp = function () {
  let messages = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  const oldestMessage = messages[0];
  return oldestMessage && oldestMessage.createdAt || null;
};
const getLatestMessageTimeStamp = function () {
  let messages = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  const latestMessage = messages[messages.length - 1];
  return latestMessage && latestMessage.createdAt || null;
};
function reducer(state, action) {
  var _state$currentGroupCh7, _action$payload, _action$payload$chann;
  switch (action.type) {
    case RESET_MESSAGES:
      return _objectSpread2(_objectSpread2({}, 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: []
      });
    case FETCH_INITIAL_MESSAGES_START:
      {
        return _objectSpread2(_objectSpread2({}, state), {}, {
          loading: true,
          allMessages: [...state.allMessages.filter(m => m.sendingStatus !== SUCCEEDED)]
        });
      }
    case FETCH_INITIAL_MESSAGES_SUCCESS:
      {
        var _state$currentGroupCh;
        const {
          currentGroupChannel,
          messages
        } = action.payload;
        if (!((currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url) === ((_state$currentGroupCh = state.currentGroupChannel) === null || _state$currentGroupCh === void 0 ? void 0 : _state$currentGroupCh.url))) {
          return state;
        }
        const oldestMessageTimeStamp = getOldestMessageTimeStamp(messages);
        const latestMessageTimeStamp = getLatestMessageTimeStamp(messages);
        return _objectSpread2(_objectSpread2({}, state), {}, {
          loading: false,
          initialized: true,
          hasMorePrev: true,
          hasMoreNext: true,
          oldestMessageTimeStamp,
          latestMessageTimeStamp,
          allMessages: [...messages]
        });
      }
    case FETCH_PREV_MESSAGES_SUCCESS:
      {
        var _state$currentGroupCh2, _messages$length, _state$messageListPar, _state$messageListPar2;
        const {
          currentGroupChannel,
          messages
        } = action.payload;
        if (!((currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url) === ((_state$currentGroupCh2 = state.currentGroupChannel) === null || _state$currentGroupCh2 === void 0 ? void 0 : _state$currentGroupCh2.url))) {
          return state;
        }
        const hasMorePrev = ((_messages$length = messages === null || messages === void 0 ? void 0 : messages.length) !== null && _messages$length !== void 0 ? _messages$length : 0) >= ((_state$messageListPar = state === null || state === void 0 ? void 0 : (_state$messageListPar2 = state.messageListParams) === null || _state$messageListPar2 === void 0 ? void 0 : _state$messageListPar2.prevResultSize) !== null && _state$messageListPar !== void 0 ? _state$messageListPar : PREV_RESULT_SIZE) + 1;
        const oldestMessageTimeStamp = getOldestMessageTimeStamp(messages);

        // Remove duplicated messages
        const duplicatedMessageIds = [];
        const updatedOldMessages = state.allMessages.map(msg => {
          const duplicatedMessage = messages.find(_ref => {
            let {
              messageId
            } = _ref;
            return compareIds(messageId, msg.messageId);
          });
          if (!duplicatedMessage) {
            return msg;
          }
          duplicatedMessageIds.push(duplicatedMessage.messageId);
          return duplicatedMessage.updatedAt > msg.updatedAt ? duplicatedMessage : msg;
        });
        const filteredNewMessages = duplicatedMessageIds.length > 0 ? messages.filter(msg => !duplicatedMessageIds.find(messageId => compareIds(messageId, msg.messageId))) : messages;
        return _objectSpread2(_objectSpread2({}, state), {}, {
          hasMorePrev,
          oldestMessageTimeStamp,
          allMessages: [...filteredNewMessages, ...updatedOldMessages]
        });
      }
    case FETCH_NEXT_MESSAGES_SUCCESS:
      {
        var _state$currentGroupCh3, _messages$length2, _state$messageListPar3, _state$messageListPar4;
        const {
          currentGroupChannel,
          messages
        } = action.payload;
        if (!((currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url) === ((_state$currentGroupCh3 = state.currentGroupChannel) === null || _state$currentGroupCh3 === void 0 ? void 0 : _state$currentGroupCh3.url))) {
          return state;
        }
        const hasMoreNext = ((_messages$length2 = messages === null || messages === void 0 ? void 0 : messages.length) !== null && _messages$length2 !== void 0 ? _messages$length2 : 0) === ((_state$messageListPar3 = state === null || state === void 0 ? void 0 : (_state$messageListPar4 = state.messageListParams) === null || _state$messageListPar4 === void 0 ? void 0 : _state$messageListPar4.nextResultSize) !== null && _state$messageListPar3 !== void 0 ? _state$messageListPar3 : NEXT_RESULT_SIZE) + 1;
        const latestMessageTimeStamp = getLatestMessageTimeStamp(messages);

        // sort ~
        const sortedMessages = mergeAndSortMessages(state.allMessages, messages);
        return _objectSpread2(_objectSpread2({}, state), {}, {
          hasMoreNext,
          latestMessageTimeStamp,
          allMessages: sortedMessages
        });
      }
    case FETCH_INITIAL_MESSAGES_FAILURE:
    case FETCH_PREV_MESSAGES_FAILURE:
    case FETCH_NEXT_MESSAGES_FAILURE:
      {
        var _state$currentGroupCh4;
        const {
          currentGroupChannel
        } = action.payload;
        if ((currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url) !== (state === null || state === void 0 ? void 0 : (_state$currentGroupCh4 = state.currentGroupChannel) === null || _state$currentGroupCh4 === void 0 ? void 0 : _state$currentGroupCh4.url)) {
          return state;
        }
        return _objectSpread2(_objectSpread2({}, state), {}, {
          loading: false,
          initialized: false,
          allMessages: [],
          hasMorePrev: false,
          hasMoreNext: false,
          oldestMessageTimeStamp: null,
          latestMessageTimeStamp: null
        });
      }
    case SEND_MESSAGEGE_START:
      return _objectSpread2(_objectSpread2({}, state), {}, {
        allMessages: [...state.allMessages, _objectSpread2({}, action.payload)]
      });
    case SEND_MESSAGEGE_SUCESS:
      {
        const message = action.payload;
        const filteredMessages = state.allMessages.filter(m => (m === null || m === void 0 ? void 0 : m.reqId) !== (message === null || message === void 0 ? void 0 : message.reqId));
        const pendingIndex = filteredMessages.findIndex(msg => (msg === null || msg === void 0 ? void 0 : msg.sendingStatus) === 'pending' || (msg === null || msg === void 0 ? void 0 : msg.sendingStatus) === 'failed');
        return _objectSpread2(_objectSpread2({}, state), {}, {
          allMessages: pendingIndex > -1 ? [...filteredMessages.slice(0, pendingIndex), message, ...filteredMessages.slice(pendingIndex)] : [...filteredMessages, message]
        });
      }
    case SEND_MESSAGEGE_FAILURE:
      {
        // eslint-disable-next-line no-param-reassign
        action.payload.failed = true;
        return _objectSpread2(_objectSpread2({}, state), {}, {
          allMessages: state.allMessages.map(m => compareIds(m.reqId, action.payload.reqId) ? action.payload : m)
        });
      }
    case SET_CURRENT_CHANNEL:
      {
        return _objectSpread2(_objectSpread2({}, state), {}, {
          currentGroupChannel: action.payload,
          isInvalid: false
        });
      }
    case SET_CHANNEL_INVALID:
      {
        return _objectSpread2(_objectSpread2({}, state), {}, {
          currentGroupChannel: null,
          isInvalid: true
        });
      }
    case ON_MESSAGE_RECEIVED:
      {
        const {
          channel,
          message
        } = action.payload;
        const {
          members
        } = channel;
        const {
          sender
        } = message;
        const {
          currentGroupChannel = {},
          unreadSince
        } = state;
        const 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(msg => msg.messageId === message.messageId)) {
          return state;
        }
        // Filter by userFilledQuery
        if (state.messageListParams && !filterMessageListParams(state.messageListParams, message)) {
          return state;
        }
        if (message.isAdminMessage && message.isAdminMessage()) {
          return _objectSpread2(_objectSpread2({}, state), {}, {
            allMessages: passUnsuccessfullMessages(state.allMessages, message)
          });
        }

        // Update members when sender profileUrl, nickname, friendName has been changed
        const senderMember = members === null || members === void 0 ? void 0 : members.find(m => (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)) {
          channel.members = members.map(member => {
            if (member.userId === sender.userId) {
              return sender;
            }
            return member;
          });
        }
        return _objectSpread2(_objectSpread2({}, state), {}, {
          currentGroupChannel: channel,
          unreadSince: state !== null && state !== void 0 && state.unreadSince ? unreadSince : format(new Date(), 'p MMM dd'),
          allMessages: passUnsuccessfullMessages(state.allMessages, message)
        });
      }
    case ON_MESSAGE_UPDATED:
      {
        var _state$currentGroupCh5;
        const {
          channel,
          message
        } = action.payload;
        const currentGroupChannelUrl = (state === null || state === void 0 ? void 0 : (_state$currentGroupCh5 = state.currentGroupChannel) === null || _state$currentGroupCh5 === void 0 ? void 0 : _state$currentGroupCh5.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 _objectSpread2(_objectSpread2({}, state), {}, {
            allMessages: state.allMessages.filter(m => !compareIds(m.messageId, message === null || message === void 0 ? void 0 : message.messageId))
          });
        }
        return _objectSpread2(_objectSpread2({}, state), {}, {
          allMessages: state.allMessages.map(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;
          })
        });
      }
    case ON_MESSAGE_THREAD_INFO_UPDATED:
      {
        var _state$currentGroupCh6;
        const {
          channel,
          event
        } = action.payload;
        const {
          channelUrl,
          threadInfo,
          targetMessageId
        } = event;
        const currentGroupChannelUrl = (state === null || state === void 0 ? void 0 : (_state$currentGroupCh6 = state.currentGroupChannel) === null || _state$currentGroupCh6 === void 0 ? void 0 : _state$currentGroupCh6.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 _objectSpread2(_objectSpread2({}, state), {}, {
          allMessages: state.allMessages.map(m => {
            if (compareIds(m.messageId, targetMessageId)) {
              // eslint-disable-next-line no-param-reassign
              m.threadInfo = threadInfo; // Upsert threadInfo to the target message
            }

            return m;
          })
        });
      }
    case RESEND_MESSAGEGE_START:
      return _objectSpread2(_objectSpread2({}, state), {}, {
        allMessages: state.allMessages.map(m => compareIds(m.reqId, action.payload.reqId) ? action.payload : m)
      });
    case MARK_AS_READ:
      if (((_state$currentGroupCh7 = state.currentGroupChannel) === null || _state$currentGroupCh7 === void 0 ? void 0 : _state$currentGroupCh7.url) !== ((_action$payload = action.payload) === null || _action$payload === void 0 ? void 0 : (_action$payload$chann = _action$payload.channel) === null || _action$payload$chann === void 0 ? void 0 : _action$payload$chann.url)) {
        return state;
      }
      return _objectSpread2(_objectSpread2({}, state), {}, {
        unreadSince: null
      });
    case ON_MESSAGE_DELETED:
      return _objectSpread2(_objectSpread2({}, state), {}, {
        allMessages: state.allMessages.filter(m => !compareIds(m.messageId, action.payload))
      });
    case ON_MESSAGE_DELETED_BY_REQ_ID:
      return _objectSpread2(_objectSpread2({}, state), {}, {
        allMessages: state.allMessages.filter(m => !compareIds(m.reqId, action.payload))
      });
    case SET_EMOJI_CONTAINER:
      {
        return _objectSpread2(_objectSpread2({}, state), {}, {
          emojiContainer: action.payload
        });
      }
    case ON_REACTION_UPDATED:
      {
        return _objectSpread2(_objectSpread2({}, state), {}, {
          allMessages: state.allMessages.map(m => {
            if (compareIds(m.messageId, action.payload.messageId)) {
              if (m.applyReactionEvent && typeof m.applyReactionEvent === 'function') {
                m.applyReactionEvent(action.payload);
              }
              return m;
            }
            return m;
          })
        });
      }
    case MESSAGE_LIST_PARAMS_CHANGED:
      {
        return _objectSpread2(_objectSpread2({}, state), {}, {
          messageListParams: action.payload
        });
      }
    default:
      return state;
  }
}

/**
 * Handles ChannelEvents and send values to dispatcher using messagesDispatcher
 * messagesDispatcher: Dispatcher
 * sdk: sdkInstance
 * logger: loggerInstance
 * channelUrl: string
 * sdkInit: bool
 */

const DELIVERY_RECIPT = 'delivery_receipt';
function useHandleChannelEvents(_ref, _ref2) {
  var _store$stores$sdkStor, _store$stores$sdkStor2, _store$stores$sdkStor3;
  let {
    sdkInit,
    currentUserId,
    currentGroupChannel,
    disableMarkAsRead
  } = _ref;
  let {
    sdk,
    logger,
    scrollRef,
    setQuoteMessage,
    messagesDispatcher
  } = _ref2;
  const store = useSendbirdStateContext();
  const {
    markAsReadScheduler,
    markAsDeliveredScheduler,
    disableMarkAsDelivered
  } = store.config;
  const canSetMarkAsDelivered = (_store$stores$sdkStor = store.stores.sdkStore.sdk) === null || _store$stores$sdkStor === void 0 ? void 0 : (_store$stores$sdkStor2 = _store$stores$sdkStor.appInfo) === null || _store$stores$sdkStor2 === void 0 ? void 0 : (_store$stores$sdkStor3 = _store$stores$sdkStor2.premiumFeatureList) === null || _store$stores$sdkStor3 === void 0 ? void 0 : _store$stores$sdkStor3.find(feature => feature === DELIVERY_RECIPT);
  useEffect(() => {
    const channelUrl = currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url;
    const channelHandlerId = uuidv4();
    if (channelUrl && sdkInit) {
      var _sdk$groupChannel;
      const channelHandler = {
        onMessageReceived: (channel, message) => {
          if (compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) {
            var _document$getElementB, _document$getElementB2;
            let scrollToEnd = false;
            try {
              const {
                current
              } = scrollRef;
              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,
                message
              }
            });
            if (scrollToEnd && ((_document$getElementB = document.getElementById('sendbird-dropdown-portal')) === null || _document$getElementB === void 0 ? void 0 : _document$getElementB.childElementCount) === 0 && ((_document$getElementB2 = document.getElementById('sendbird-emoji-list-portal')) === null || _document$getElementB2 === void 0 ? void 0 : _document$getElementB2.childElementCount) === 0) {
              // and !openContextMenu
              try {
                setTimeout(() => {
                  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: 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
            });
          }
        },
        // before(onDeliveryReceiptUpdated)
        onUndeliveredMemberStatusUpdated: 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: (channel, message) => {
          logger.info('Channel | useHandleChannelEvents: onMessageUpdated', message);
          messagesDispatcher({
            type: ON_MESSAGE_UPDATED,
            payload: {
              channel,
              message
            }
          });
        },
        onThreadInfoUpdated: (channel, threadInfoUpdateEvent) => {
          logger.info('Channel | useHandleChannelEvents: onThreadInfoUpdated', {
            channel,
            threadInfoUpdateEvent
          });
          messagesDispatcher({
            type: ON_MESSAGE_THREAD_INFO_UPDATED,
            payload: {
              channel,
              event: threadInfoUpdateEvent
            }
          });
        },
        onMessageDeleted: (channel, messageId) => {
          logger.info('Channel | useHandleChannelEvents: onMessageDeleted', {
            channel,
            messageId
          });
          setQuoteMessage(null);
          messagesDispatcher({
            type: ON_MESSAGE_DELETED,
            payload: messageId
          });
        },
        onReactionUpdated: (channel, reactionEvent) => {
          logger.info('Channel | useHandleChannelEvents: onReactionUpdated', {
            channel,
            reactionEvent
          });
          messagesDispatcher({
            type: ON_REACTION_UPDATED,
            payload: reactionEvent
          });
        },
        onChannelChanged: channel => {
          if (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: channel => {
          if (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: channel => {
          if (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: (channel, user) => {
          if (compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) {
            logger.info('Channel | useHandleChannelEvents: onUserMuted', {
              channel,
              user
            });
            messagesDispatcher({
              type: SET_CURRENT_CHANNEL,
              payload: channel
            });
          }
        },
        onUserUnmuted: (channel, user) => {
          if (compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) {
            logger.info('Channel | useHandleChannelEvents: onUserUnmuted', {
              channel,
              user
            });
            messagesDispatcher({
              type: SET_CURRENT_CHANNEL,
              payload: channel
            });
          }
        },
        onUserBanned: (channel, user) => {
          var _sdk$currentUser;
          if (compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl) && (user === null || user === void 0 ? void 0 : user.userId) === (sdk === null || sdk === void 0 ? void 0 : (_sdk$currentUser = sdk.currentUser) === null || _sdk$currentUser === void 0 ? void 0 : _sdk$currentUser.userId)) {
            logger.info('Channel | useHandleChannelEvents: onUserBanned', {
              channel,
              user
            });
            messagesDispatcher({
              type: SET_CURRENT_CHANNEL,
              payload: null
            });
          }
        },
        onOperatorUpdated: (channel, users) => {
          if (compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) {
            logger.info('Channel | useHandleChannelEvents: onOperatorUpdated', {
              channel,
              users
            });
            messagesDispatcher({
              type: SET_CURRENT_CHANNEL,
              payload: channel
            });
          }
        },
        onUserLeft: (channel, user) => {
          if (compareIds(channel === null || channel === void 0 ? void 0 : channel.url, channelUrl)) {
            logger.info('Channel | useHandleChannelEvents: onUserLeft', {
              channel,
              user
            });
            if ((user === null || user === void 0 ? void 0 : user.userId) === currentUserId) {
              messagesDispatcher({
                type: SET_CURRENT_CHANNEL,
                payload: null
              });
            }
          }
        }
      };
      logger.info('Channel | useHandleChannelEvents: Setup event handler', {
        channelHandlerId,
        channelHandler
      });
      // Add this group channel handler to the Sendbird chat instance
      (_sdk$groupChannel = sdk.groupChannel) === null || _sdk$groupChannel === void 0 ? void 0 : _sdk$groupChannel.addGroupChannelHandler(channelHandlerId, new GroupChannelHandler(channelHandler));
    }
    return () => {
      var _sdk$groupChannel2;
      if (sdk !== null && sdk !== void 0 && (_sdk$groupChannel2 = sdk.groupChannel) !== null && _sdk$groupChannel2 !== void 0 && _sdk$groupChannel2.removeGroupChannelHandler) {
        logger.info('Channel | useHandleChannelEvents: Removing message reciver handler', channelHandlerId);
        sdk.groupChannel.removeGroupChannelHandler(channelHandlerId);
      } else if (sdk !== null && sdk !== void 0 && sdk.groupChannel) {
        logger.error('Channel | useHandleChannelEvents: Not found the removeGroupChannelHandler');
      }
    };
  }, [currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url, sdkInit]);
}

function useSetChannel(_ref, _ref2) {
  let {
    channelUrl,
    sdkInit,
    disableMarkAsRead
  } = _ref;
  let {
    messagesDispatcher,
    sdk,
    logger,
    markAsReadScheduler
  } = _ref2;
  useEffect(() => {
    if (channelUrl && sdkInit && sdk && sdk.groupChannel) {
      logger.info('Channel | useSetChannel fetching channel', channelUrl);
      sdk.groupChannel.getChannel(channelUrl).then(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(e => {
        logger.warning('Channel | useSetChannel fetch channel failed', {
          channelUrl,
          e
        });
        messagesDispatcher({
          type: SET_CHANNEL_INVALID
        });
      });
      sdk.getAllEmoji().then(emojiContainer_ => {
        logger.info('Channel: Getting emojis success', emojiContainer_);
        messagesDispatcher({
          type: SET_EMOJI_CONTAINER,
          payload: emojiContainer_
        });
      }).catch(err => {
        logger.error('Channel: Getting emojis failed', err);
      });
      sdk.getAllEmoji();
    }
  }, [channelUrl, sdkInit]);
}

function useInitialMessagesFetch(_ref, _ref2) {
  let {
    currentGroupChannel,
    userFilledMessageListQuery,
    initialTimeStamp,
    replyType
  } = _ref;
  let {
    logger,
    scrollRef,
    messagesDispatcher
  } = _ref2;
  const channelUrl = currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url;
  useEffect(() => {
    logger.info('Channel useInitialMessagesFetch: Setup started', currentGroupChannel);
    messagesDispatcher({
      type: RESET_MESSAGES,
      payload: null
    });
    if (currentGroupChannel && currentGroupChannel !== null && currentGroupChannel !== void 0 && currentGroupChannel.getMessagesByTimestamp) {
      const messageListParams = {};
      messageListParams.prevResultSize = PREV_RESULT_SIZE;
      if (initialTimeStamp) {
        messageListParams.nextResultSize = NEXT_RESULT_SIZE;
      }
      messageListParams.isInclusive = true;
      messageListParams.includeReactions = true;
      messageListParams.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(key => {
          messageListParams[key] = userFilledMessageListQuery[key];
        });
      }
      if (replyType && (replyType === 'QUOTE_REPLY' || replyType === 'THREAD') || userFilledMessageListQuery) {
        logger.info('Channel useInitialMessagesFetch: Setup messageListParams', messageListParams);
        messagesDispatcher({
          type: MESSAGE_LIST_PARAMS_CHANGED,
          payload: messageListParams
        });
      }
      logger.info('Channel: Fetching messages', {
        currentGroupChannel,
        userFilledMessageListQuery
      });
      messagesDispatcher({
        type: FETCH_INITIAL_MESSAGES_START,
        payload: null
      });
      currentGroupChannel.getMessagesByTimestamp(initialTimeStamp || new Date().getTime(), messageListParams).then(messages => {
        messagesDispatcher({
          type: FETCH_INITIAL_MESSAGES_SUCCESS,
          payload: {
            currentGroupChannel,
            messages
          }
        });
      }).catch(error => {
        logger.error('Channel: Fetching messages failed', error);
        messagesDispatcher({
          type: FETCH_INITIAL_MESSAGES_FAILURE,
          payload: {
            currentGroupChannel
          }
        });
      }).finally(() => {
        if (!initialTimeStamp) {
          setTimeout(() => scrollIntoLast(0, scrollRef));
        } else {
          setTimeout(() => {
            scrollToRenderedMessage(scrollRef, initialTimeStamp);
          }, 500);
        }
      });
    }
  }, [channelUrl, userFilledMessageListQuery, initialTimeStamp]);
  /**
   * Note - useEffect(() => {}, [currentGroupChannel])
   * was buggy, that is why we did
   * const channelUrl = currentGroupChannel && currentGroupChannel.url;
   * useEffect(() => {}, [channelUrl])
   * Again, this hook is supposed to execute when currentGroupChannel changes
   * The 'channelUrl' here is not the same memory reference from Conversation.props
   */
}

function useHandleReconnect(_ref, _ref2) {
  let {
    isOnline,
    replyType,
    disableMarkAsRead
  } = _ref;
  let {
    logger,
    sdk,
    scrollRef,
    currentGroupChannel,
    messagesDispatcher,
    markAsReadScheduler,
    userFilledMessageListQuery
  } = _ref2;
  useEffect(() => {
    const wasOffline = !isOnline;
    return () => {
      // state changed from offline to online
      if (wasOffline && currentGroupChannel !== null && currentGroupChannel !== void 0 && currentGroupChannel.url) {
        var _sdk$appInfo, _sdk$groupChannel;
        logger.info('Refreshing conversation state');
        const isReactionEnabled = (sdk === null || sdk === void 0 ? void 0 : (_sdk$appInfo = sdk.appInfo) === null || _sdk$appInfo === void 0 ? void 0 : _sdk$appInfo.useReaction) || false;
        const messageListParams = {
          prevResultSize: PREV_RESULT_SIZE,
          isInclusive: true,
          includeReactions: isReactionEnabled,
          nextResultSize: NEXT_RESULT_SIZE
        };
        if (replyType && replyType === 'QUOTE_REPLY') {
          messageListParams.includeThreadInfo = true;
          messageListParams.includeParentMessageInfo = true;
          messageListParams.replyType = ReplyType.ONLY_REPLY_TO_CHANNEL;
        }
        if (userFilledMessageListQuery) {
          Object.keys(userFilledMessageListQuery).forEach(key => {
            messageListParams[key] = userFilledMessageListQuery[key];
          });
        }
        logger.info('Channel: Fetching messages', {
          currentGroupChannel,
          userFilledMessageListQuery
        });
        messagesDispatcher({
          type: FETCH_INITIAL_MESSAGES_START,
          payload: null
        });
        sdk === null || sdk === void 0 ? void 0 : (_sdk$groupChannel = sdk.groupChannel) === null || _sdk$groupChannel === void 0 ? void 0 : _sdk$groupChannel.getChannel(currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url).then(groupChannel => {
          const lastMessageTime = new Date().getTime();
          groupChannel.getMessagesByTimestamp(lastMessageTime, messageListParams).then(messages => {
            messagesDispatcher({
              type: FETCH_INITIAL_MESSAGES_SUCCESS,
              payload: {
                currentGroupChannel,
                messages
              }
            });
            setTimeout(() => scrollIntoLast(0, scrollRef));
          }).catch(error => {
            logger.error('Channel: Fetching messages failed', error);
            messagesDispatcher({
              type: FETCH_INITIAL_MESSAGES_FAILURE,
              payload: {
                currentGroupChannel
              }
            });
          });
          if (!disableMarkAsRead) {
            markAsReadScheduler.push(currentGroupChannel);
          }
        });
      }
    };
  }, [isOnline, replyType]);
}

function useScrollCallback(_ref, _ref2) {
  let {
    currentGroupChannel,
    oldestMessageTimeStamp,
    userFilledMessageListQuery,
    replyType
  } = _ref;
  let {
    hasMorePrev,
    logger,
    messagesDispatcher,
    sdk
  } = _ref2;
  return useCallback(cb => {
    if (!hasMorePrev) {
      return;
    }
    const {
      appInfo = {}
    } = sdk;
    const isReactionEnabled = appInfo.useReaction || false;
    const messageListParams = {
      prevResultSize: PREV_RESULT_SIZE,
      isInclusive: true,
      includeReactions: isReactionEnabled
    };
    messageListParams.includeMetaArray = true;
    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(key => {
        messageListParams[key] = userFilledMessageListQuery[key];
      });
    }
    logger.info('Channel: Fetching messages', {
      currentGroupChannel,
      userFilledMessageListQuery
    });
    currentGroupChannel.getMessagesByTimestamp(oldestMessageTimeStamp || new Date().getTime(), messageListParams).then(messages => {
      messagesDispatcher({
        type: FETCH_PREV_MESSAGES_SUCCESS,
        payload: {
          currentGroupChannel,
          messages
        }
      });
      cb([messages, null]);
    }).catch(error => {
      logger.error('Channel: Fetching messages failed', error);
      messagesDispatcher({
        type: FETCH_PREV_MESSAGES_FAILURE,
        payload: {
          currentGroupChannel
        }
      });
      cb([null, error]);
    });
  }, [currentGroupChannel, oldestMessageTimeStamp, replyType]);
}

function useScrollDownCallback(_ref, _ref2) {
  let {
    currentGroupChannel,
    latestMessageTimeStamp,
    userFilledMessageListQuery,
    hasMoreNext,
    replyType
  } = _ref;
  let {
    logger,
    messagesDispatcher,
    sdk
  } = _ref2;
  return useCallback(cb => {
    if (!hasMoreNext) {
      return;
    }
    const {
      appInfo = {}
    } = sdk;
    const isReactionEnabled = appInfo.useReaction || false;
    const messageListParams = {
      nextResultSize: NEXT_RESULT_SIZE,
      isInclusive: true,
      includeReactions: isReactionEnabled
    };
    messageListParams.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(key => {
        messageListParams[key] = userFilledMessageListQuery[key];
      });
    }
    logger.info('Channel: Fetching later messages', {
      currentGroupChannel,
      userFilledMessageListQuery
    });
    currentGroupChannel.getMessagesByTimestamp(latestMessageTimeStamp || new Date().getTime(), messageListParams).then(messages => {
      messagesDispatcher({
        type: FETCH_NEXT_MESSAGES_SUCCESS,
        payload: {
          currentGroupChannel,
          messages
        }
      });
      cb([messages, null]);
    }).catch(error => {
      logger.error('Channel: Fetching later messages failed', error);
      messagesDispatcher({
        type: FETCH_NEXT_MESSAGES_FAILURE,
        payload: {
          currentGroupChannel
        }
      });
      cb([null, error]);
    });
  }, [currentGroupChannel, latestMessageTimeStamp, hasMoreNext, replyType]);
}

function useDeleteMessageCallback(_ref, _ref2) {
  let {
    currentGroupChannel,
    messagesDispatcher
  } = _ref;
  let {
    logger
  } = _ref2;
  return useCallback(message => {
    logger.info('Channel | useDeleteMessageCallback: Deleting message', message);
    const {
      requestState
    } = message;
    return new Promise((resolve, reject) => {
      logger.info('Channel | useDeleteMessageCallback: Deleting message requestState:', requestState);
      // Message is only on local
      if (requestState === 'failed' || requestState === 'pending') {
        logger.info('Channel | useDeleteMessageCallback: Deleted message from local:', message);
        messagesDispatcher({
          type: ON_MESSAGE_DELETED_BY_REQ_ID,
          payload: message.reqId
        });
        resolve(message);
      }
      logger.info('Channel | useDeleteMessageCallback: Deleting message from remote:', requestState);
      currentGroupChannel.deleteMessage(message).then(() => {
        logger.info('Channel | useDeleteMessageCallback: Deleting message success!', message);
        messagesDispatcher({
          type: ON_MESSAGE_DELETED,
          payload: message.messageId
        });
        resolve(message);
      }).catch(err => {
        logger.warning('Channel | useDeleteMessageCallback: Deleting message failed!', err);
        reject(err);
      });
    });
  }, [currentGroupChannel, messagesDispatcher]);
}

function useUpdateMessageCallback(_ref, _ref2) {
  let {
    currentGroupChannel,
    messagesDispatcher,
    onBeforeUpdateUserMessage,
    isMentionEnabled
  } = _ref;
  let {
    logger,
    pubSub
  } = _ref2;
  return useCallback((props, callback) => {
    const {
      messageId,
      message,
      mentionedUsers,
      mentionTemplate
    } = props;
    const createParamsDefault = () => {
      const params = {};
      params.message = message;
      if (isMentionEnabled && (mentionedUsers === null || mentionedUsers === void 0 ? void 0 : mentionedUsers.length) > 0) {
        params.mentionedUsers = mentionedUsers;
      }
      if (isMentionEnabled && mentionTemplate) {
        params.mentionedMessageTemplate = mentionTemplate;
      } else {
        params.mentionedMessageTemplate = message;
      }
      return params;
    };
    const createCustomPrams = onBeforeUpdateUserMessage && typeof onBeforeUpdateUserMessage === 'function';
    if (createCustomPrams) {
      logger.info('Channel: creating params using onBeforeUpdateUserMessage', onBeforeUpdateUserMessage);
    }
    const params = onBeforeUpdateUserMessage ? onBeforeUpdateUserMessage(message) : createParamsDefault();
    logger.info('Channel: Updating message!', params);
    currentGroupChannel.updateUserMessage(messageId, params).then((msg, err) => {
      if (callback) {
        callback(err, msg);
      }
      logger.info('Channel: Updating message success!', msg);
      messagesDispatcher({
        type: ON_MESSAGE_UPDATED,
        payload: {
          channel: currentGroupChannel,
          message: msg
        }
      });
      pubSub.publish(PUBSUB_TOPICS.UPDATE_USER_MESSAGE, {
        message: msg,
        channel: currentGroupChannel
      });
    });
  }, [currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.url, messagesDispatcher, onBeforeUpdateUserMessage]);
}

function useResendMessageCallback(_ref, _ref2) {
  let {
    currentGroupChannel,
    messagesDispatcher
  } = _ref;
  let {
    logger
  } = _ref2;
  return useCallback(failedMessage => {
    logger.info('Channel: Resending message has started', failedMessage);
    const {
      messageType,
      file
    } = failedMessage;
    if (failedMessage !== null && failedMessage !== void 0 && failedMessage.isResendable) {
      // Move the logic setting sendingStatus to pending into the reducer
      // eslint-disable-next-line no-param-reassign
      failedMessage.requestState = 'pending';
      // eslint-disable-next-line no-param-reassign
      failedMessage.sendingStatus = 'pending';
      messagesDispatcher({
        type: RESEND_MESSAGEGE_START,
        payload: failedMessage
      });

      // userMessage
      if (messageType === 'user') {
        currentGroupChannel.resendUserMessage(failedMessage).then(message => {
          logger.info('Channel: Resending message success!', message);
          messagesDispatcher({
            type: SEND_MESSAGEGE_SUCESS,
            payload: message
          });
        }).catch(e => {
          logger.warning('Channel: Resending message failed!', e);
          // eslint-disable-next-line no-param-reassign
          failedMessage.requestState = 'failed';
          // eslint-disable-next-line no-param-reassign
          failedMessage.sendingStatus = 'failed';
          messagesDispatcher({
            type: SEND_MESSAGEGE_FAILURE,
            payload: failedMessage
          });
        });

        // eslint-disable-next-line no-param-reassign
        failedMessage.requestState = 'pending';
        // eslint-disable-next-line no-param-reassign
        failedMessage.sendingStatus = 'pending';
        messagesDispatcher({
          type: RESEND_MESSAGEGE_START,
          payload: failedMessage
        });
        return;
      }
      if (messageType === 'file') {
        currentGroupChannel.resendFileMessage(failedMessage, file).then(message => {
          logger.info('Channel: Resending file message success!', message);
          messagesDispatcher({
            type: SEND_MESSAGEGE_SUCESS,
            payload: message
          });
        }).catch(e => {
          logger.warning('Channel: Resending file message failed!', e);
          // eslint-disable-next-line no-param-reassign
          failedMessage.requestState = 'failed';
          // eslint-disable-next-line no-param-reassign
          failedMessage.sendingStatus = 'failed';
          messagesDispatcher({
            type: SEND_MESSAGEGE_FAILURE,
            payload: failedMessage
          });
        });

        // eslint-disable-next-line no-param-reassign
        failedMessage.requestState = 'pending';
        // eslint-disable-next-line no-param-reassign
        failedMessage.sendingStatus = 'pending';
        messagesDispatcher({
          type: RESEND_MESSAGEGE_START,
          payload: failedMessage
        });
      }
    } else {
      // to alert user on console
      // eslint-disable-next-line no-console
      console.error('Message is not resendable');
      logger.warning('Message is not resendable', failedMessage);
    }
  }, [currentGroupChannel, messagesDispatcher]);
}

function useSendMessageCallback(_ref, _ref2) {
  let {
    isMentionEnabled,
    currentGroupChannel,
    onBeforeSendUserMessage
  } = _ref;
  let {
    logger,
    pubSub,
    scrollRef,
    messagesDispatcher
  } = _ref2;
  const messageInputRef = useRef(null);
  const sendMessage = useCallback(props => {
    const {
      quoteMessage = null,
      message,
      mentionTemplate,
      // mentionedUserIds,
      mentionedUsers
    } = props;
    const createParamsDefault = () => {
      const params = {};
      params.message = message;
      // if (isMentionEnabled && mentionedUserIds?.length > 0) {
      if (isMentionEnabled && (mentionedUsers === null || mentionedUsers === void 0 ? void 0 : mentionedUsers.length) > 0) {
        // params.mentionedUserIds = mentionedUserIds;
        params.mentionedUsers = mentionedUsers;
      }
      // if (isMentionEnabled && mentionTemplate && mentionedUserIds?.length > 0) {
      if (isMentionEnabled && mentionTemplate && (mentionedUsers === null || mentionedUsers === void 0 ? void 0 : mentionedUsers.length) > 0) {
        params.mentionedMessageTemplate = mentionTemplate;
      }
      if (quoteMessage) {
        params.isReplyToChannel = true;
        params.parentMessageId = quoteMessage.messageId;
      }
      return params;
    };
    const createCustomPrams = onBeforeSendUserMessage && typeof onBeforeSendUserMessage === 'function';
    if (createCustomPrams) {
      logger.info('Channel: creating params using onBeforeSendUserMessage', onBeforeSendUserMessage);
    }
    const params = onBeforeSendUserMessage ? onBeforeSendUserMessage(message, quoteMessage) : createParamsDefault();
    logger.info('Channel: Sending message has started', params);
    currentGroupChannel.sendUserMessage(params).onPending(pendingMsg => {
      pubSub.publish(PUBSUB_TOPICS.SEND_MESSAGE_START, {
        /* pubSub is used instead of messagesDispatcher
          to avoid redundantly calling `messageActionTypes.SEND_MESSAGEGE_START` */
        message: pendingMsg,
        channel: currentGroupChannel
      });
      setTimeout(() => scrollIntoLast(0, scrollRef));
    }).onFailed((err, msg) => {
      logger.warning('Channel: Sending message failed!', {
        message: msg,
        error: err
      });
      messagesDispatcher({
        type: SEND_MESSAGEGE_FAILURE,
        payload: msg
      });
    }).onSucceeded(msg => {
      logger.info('Channel: Sending message success!', msg);
      messagesDispatcher({
        type: SEND_MESSAGEGE_SUCESS,
        payload: msg
      });
    });
  }, [currentGroupChannel, onBeforeSendUserMessage]);
  return [messageInputRef, sendMessage];
}

function useSendFileMessageCallback(_ref, _ref2) {
  let {
    currentGroupChannel,
    onBeforeSendFileMessage,
    imageCompression = {}
  } = _ref;
  let {
    logger,
    pubSub,
    scrollRef,
    messagesDispatcher
  } = _ref2;
  const sendMessage = useCallback(function (file) {
    let quoteMessage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
    const {
      compressionRate,
      resizingWidth,
      resizingHeight
    } = imageCompression;
    const createCustomParams = onBeforeSendFileMessage && typeof onBeforeSendFileMessage === 'function';
    const compressibleFileType = file.type === 'image/jpg' || file.type === 'image/png' || file.type === 'image/jpeg';
    const compressibleRatio = compressionRate > 0 && compressionRate < 1;
    // pxToNumber returns null if values are invalid
    const compressibleDiamensions = pxToNumber(resizingWidth) || pxToNumber(resizingHeight);
    const canCompressImage = compressibleFileType && (compressibleRatio || compressibleDiamensions);
    const createParamsDefault = file_ => {
      const params = {};
      params.file = file_;
      if (quoteMessage) {
        params.isReplyToChannel = true;
        params.parentMessageId = quoteMessage.messageId;
      }
      return params;
    };
    if (canCompressImage) {
      // Using image compression
      try {
        const image = document.createElement('img');
        image.src = URL.createObjectURL(file);
        image.onload = () => {
          URL.revokeObjectURL(image.src);
          const canvas = document.createElement('canvas');
          const imageWdith = image.naturalWidth || image.width;
          const imageHeight = image.naturalHeight || image.height;
          let targetWidth = pxToNumber(resizingWidth) || imageWdith;
          let targetHeight = pxToNumber(resizingHeight) || imageHeight;

          // In canvas.toBlob(callback, mimeType, qualityArgument)
          // qualityArgument doesnt work
          // so in case compressibleDiamensions are not present, we use ratio
          if (file.type === 'image/png' && !compressibleDiamensions) {
            targetWidth *= compressionRate;
            targetHeight *= compressionRate;
          }
          canvas.width = targetWidth;
          canvas.height = targetHeight;
          const context = canvas.getContext('2d');
          context.drawImage(image, 0, 0, targetWidth, targetHeight);
          context.canvas.toBlob(newImageBlob => {
            const compressedFile = new File([newImageBlob], file.name, {
              type: file.type
            });
            if (createCustomParams) {
              logger.info('Channel: Creating params using onBeforeSendFileMessage', onBeforeSendFileMessage);
            }
            const params = createCustomParams ? onBeforeSendFileMessage(compressedFile, quoteMessage) : createParamsDefault(compressedFile);
            logger.info('Channel: Uploading file message start!', params);
            currentGroupChannel.sendFileMessage(params).onPending(pendingMessage => {
              pubSub.publish(PUBSUB_TOPICS.SEND_MESSAGE_START, {
                /* pubSub is used instead of messagesDispatcher
                  to avoid redundantly calling `messageActionTypes.SEND_MESSAGEGE_START` */
                message: _objectSpread2(_objectSpread2({}, pendingMessage), {}, {
                  url: URL.createObjectURL(compressedFile),
                  // pending thumbnail message seems to be failed
                  requestState: 'pending'
                }),
                channel: currentGroupChannel
              });
              setTimeout(() => scrollIntoLast(0, scrollRef), 1000);
            }).onFailed((err, failedMessage) => {
              logger.error('Channel: Sending file message failed!', {
                failedMessage,
                err
              });
              // eslint-disable-next-line no-param-reassign
              failedMessage.localUrl = URL.createObjectURL(compressedFile);
              // eslint-disable-next-line no-param-reassign
              failedMessage.file = compressedFile;
              messagesDispatcher({
                type: SEND_MESSAGEGE_FAILURE,
                payload: failedMessage
              });
            }).onSucceeded(succeededMessage => {
              logger.info('Channel: Sending file message success!', succeededMessage);
              messagesDispatcher({
                type: SEND_MESSAGEGE_SUCESS,
                payload: succeededMessage
              });
            });
          }, file.type, compressionRate);
        };
      } catch (error) {
        logger.error('Channel: Sending file message failed!', error);
      }
    } else {
      // Not using image compression
      if (createCustomParams) {
        logger.info('Channel: creating params using onBeforeSendFileMessage', onBeforeSendFileMessage);
      }
      const params = onBeforeSendFileMessage ? onBeforeSendFileMessage(file, quoteMessage) : createParamsDefault(file);
      logger.info('Channel: Uploading file message start!', params);
      currentGroupChannel.sendFileMessage(params).onPending(pendingMsg => {
        pubSub.publish(PUBSUB_TOPICS.SEND_MESSAGE_START, {
          /* pubSub is used instead of messagesDispatcher
            to avoid redundantly calling `messageActionTypes.SEND_MESSAGEGE_START` */
          message: _objectSpread2(_objectSpread2({}, pendingMsg), {}, {
            url: URL.createObjectURL(file),
            // pending thumbnail message seems to be failed
            requestState: 'pending'
          }),
          channel: currentGroupChannel
        });
        setTimeout(() => scrollIntoLast(0, scrollRef), 1000);
      }).onFailed((error, message) => {
        logger.error('Channel: Sending file message failed!', {
          message,
          error
        });
        // eslint-disable-next-line no-param-reassign
        message.localUrl = URL.createObjectURL(file);
        // eslint-disable-next-line no-param-reassign
        message.file = file;
        messagesDispatcher({
          type: SEND_MESSAGEGE_FAILURE,
          payload: message
        });
      }).onSucceeded(message => {
        logger.info('Channel: Sending message success!', message);
        messagesDispatcher({
          type: SEND_MESSAGEGE_SUCESS,
          payload: message
        });
      });
    }
  }, [currentGroupChannel, onBeforeSendFileMessage, imageCompression]);
  return [sendMessage];
}

function useToggleReactionCallback(_ref, _ref2) {
  let {
    currentGroupChannel
  } = _ref;
  let {
    logger
  } = _ref2;
  return useCallback((message, key, isReacted) => {
    if (isReacted) {
      currentGroupChannel.deleteReaction(message, key).then(res => {
        logger.info('Delete reaction success', res);
      }).catch(err => {
        logger.warning('Delete reaction failed', err);
      });
      return;
    }
    currentGroupChannel.addReaction(message, key).then(res => {
      logger.info('Add reaction success', res);
    }).catch(err => {
      logger.warning('Add reaction failed', err);
    });
  }, [currentGroupChannel]);
}

// To prevent multiple clicks on the message in the channel while scrolling
function deactivateClick(scrollRef) {
  const element = scrollRef.current;
  const parentNode = element === null || element === void 0 ? void 0 : element.parentNode;
  if (element && parentNode) {
    element.style.pointerEvents = 'none';
    parentNode.style.cursor = 'wait';
  }
}
function activateClick(scrollRef) {
  const element = scrollRef.current;
  const parentNode = element === null || element === void 0 ? void 0 : element.parentNode;
  if (element && parentNode) {
    element.style.pointerEvents = 'auto';
    parentNode.style.cursor = 'auto';
  }
}
function useScrollToMessage(_ref, _ref2) {
  let {
    setInitialTimeStamp,
    setAnimatedMessageId,
    allMessages,
    scrollRef
  } = _ref;
  let {
    logger
  } = _ref2;
  return useCallback((createdAt, messageId) => {
    const isPresent = allMessages.find(m => m.messageId === messageId);
    setAnimatedMessageId(null);
    setTimeout(() => {
      try {
        logger.info('Channel: scroll to message - disabling mouse events');
        deactivateClick(scrollRef);
        if (isPresent) {
          logger.info('Channel: scroll to message - message is present');
          setAnimatedMessageId(messageId);
          scrollToRenderedMessage(scrollRef, createdAt);
        } else {
          logger.info('Channel: scroll to message - fetching older messages');
          setInitialTimeStamp(null);
          setInitialTimeStamp(createdAt);
          setAnimatedMessageId(messageId);
        }
      } finally {
        logger.info('Channel: scroll to message - enabled mouse events');
        activateClick(scrollRef);
      }
    });
  }, [setInitialTimeStamp, setAnimatedMessageId, allMessages]);
}

const useSendVoiceMessageCallback = (_ref, _ref2) => {
  let {
    currentGroupChannel,
    onBeforeSendVoiceMessage
  } = _ref;
  let {
    logger,
    pubSub,
    scrollRef,
    messagesDispatcher
  } = _ref2;
  const sendMessage = useCallback((file, duration, quoteMessage) => {
    const messageParams = onBeforeSendVoiceMessage && typeof onBeforeSendVoiceMessage === 'function' ? onBeforeSendVoiceMessage(file, quoteMessage) : {
      file,
      fileName: VOICE_MESSAGE_FILE_NAME,
      mimeType: VOICE_MESSAGE_MIME_TYPE,
      metaArrays: [new MessageMetaArray({
        key: META_ARRAY_VOICE_DURATION_KEY,
        value: [`${duration}`]
      }), new MessageMetaArray({
        key: META_ARRAY_MESSAGE_TYPE_KEY,
        value: [META_ARRAY_MESSAGE_TYPE_VALUE__VOICE]
      })]
    };
    if (quoteMessage) {
      messageParams.isReplyToChannel = true;
      messageParams.parentMessageId = quoteMessage.messageId;
    }
    logger.info('Channel: Start sending voice message', messageParams);
    currentGroupChannel.sendFileMessage(messageParams).onPending(pendingMessage => {
      pubSub.publish(PUBSUB_TOPICS.SEND_MESSAGE_START, {
        /* pubSub is used instead of messagesDispatcher
          to avoid redundantly calling `messageActionTypes.SEND_MESSAGEGE_START` */
        message: pendingMessage,
        channel: currentGroupChannel
      });
      setTimeout(() => scrollIntoLast(0, scrollRef), 1000);
    }).onFailed((err, failedMessage) => {
      logger.error('Channel: Sending voice message failed!', {
        failedMessage,
        err
      });
      messagesDispatcher({
        type: SEND_MESSAGEGE_FAILURE,
        payload: failedMessage
      });
    }).onSucceeded(succeededMessage => {
      logger.info('Channel: Sending voice message success!', succeededMessage);
      messagesDispatcher({
        type: SEND_MESSAGEGE_SUCESS,
        payload: succeededMessage
      });
    });
  }, [currentGroupChannel, onBeforeSendVoiceMessage]);
  return [sendMessage];
};

const ChannelContext = /*#__PURE__*/React__default.createContext(undefined);
const ChannelProvider = props => {
  var _globalStore$stores, _globalStore$stores$s, _globalStore$stores2, _globalStore$stores2$, _ref, _props$disableUserPro;
  const {
    channelUrl,
    children,
    isReactionEnabled,
    isMessageGroupingEnabled = true,
    showSearchIcon,
    animatedMessage,
    highlightedMessage,
    startingPoint,
    onBeforeSendUserMessage,
    onBeforeSendFileMessage,
    onBeforeUpdateUserMessage,
    onBeforeSendVoiceMessage,
    onChatHeaderActionClick,
    onSearchClick,
    onBackClick,
    replyType: channelReplyType,
    threadReplySelectType,
    queries,
    filterMessageList,
    disableMarkAsRead = false,
    onReplyInThread,
    onQuoteMessageClick,
    onMessageAnimated,
    onMessageHighlighted,
    scrollBehavior = 'auto'
  } = props;
  const globalStore = useSendbirdStateContext();
  const {
    config
  } = globalStore;
  const replyType = channelReplyType !== null && channelReplyType !== void 0 ? channelReplyType : config.replyType;
  const {
    pubSub,
    logger,
    userId,
    isOnline,
    imageCompression,
    isMentionEnabled,
    isVoiceMessageEnabled,
    onUserProfileMessage,
    markAsReadScheduler,
    groupChannel
  } = config;
  const sdk = globalStore === null || globalStore === void 0 ? void 0 : (_globalStore$stores = globalStore.stores) === null || _globalStore$stores === void 0 ? void 0 : (_globalStore$stores$s = _globalStore$stores.sdkStore) === null || _globalStore$stores$s === void 0 ? void 0 : _globalStore$stores$s.sdk;
  const sdkInit = globalStore === null || globalStore === void 0 ? void 0 : (_globalStore$stores2 = globalStore.stores) === null || _globalStore$stores2 === void 0 ? void 0 : (_globalStore$stores2$ = _globalStore$stores2.sdkStore) === null || _globalStore$stores2$ === void 0 ? void 0 : _globalStore$stores2$.initialized;
  const globalConfigs = globalStore === null || globalStore === void 0 ? void 0 : globalStore.config;
  const [initialTimeStamp, setInitialTimeStamp] = useState(startingPoint);
  useEffect(() => {
    setInitialTimeStamp(startingPoint);
  }, [startingPoint, channelUrl]);
  const [animatedMessageId, setAnimatedMessageId] = useState(0);
  const [highLightedMessageId, setHighLightedMessageId] = useState(highlightedMessage);
  useEffect(() => {
    setHighLightedMessageId(highlightedMessage);
  }, [highlightedMessage]);
  const userFilledMessageListQuery = queries === null || queries === void 0 ? void 0 : queries.messageListParams;
  const [quoteMessage, setQuoteMessage] = useState(null);
  const [messagesStore, messagesDispatcher] = useReducer(reducer, messagesInitialState);
  const scrollRef = useRef(null);
  const {
    allMessages,
    loading,
    initialized,
    unreadSince,
    isInvalid,
    currentGroupChannel,
    hasMorePrev,
    oldestMessageTimeStamp,
    hasMoreNext,
    latestMessageTimeStamp,
    emojiContainer,
    readStatus
  } = messagesStore;
  const isSuper = (currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.isSuper) || false;
  const isBroadcast = (currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.isBroadcast) || false;
  const usingReaction = getIsReactionEnabled({
    isBroadcast,
    isSuper,
    globalLevel: config === null || config === void 0 ? void 0 : config.isReactionEnabled,
    moduleLevel: isReactionEnabled
  });
  const emojiAllMap = useMemo(() => usingReaction ? getAllEmojisMapFromEmojiContainer(emojiContainer) : new Map(), [emojiContainer]);
  const nicknamesMap = useMemo(() => usingReaction && currentGroupChannel ? getNicknamesMapFromMembers(currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.members) : new Map(), [currentGroupChannel === null || currentGroupChannel === void 0 ? void 0 : currentGroupChannel.members]);

  // Animate message
  useEffect(() => {
    if (animatedMessage) {
      setAnimatedMessageId(animatedMessage);
    }
  }, [animatedMessage]);

  // Scrollup is default scroll for channel
  const onScrollCallback = useScrollCallback({
    currentGroupChannel,
    oldestMessageTimeStamp,
    userFilledMessageListQuery,
    replyType,
    isVoiceMessageEnabled
  }, {
    hasMorePrev,
    logger,
    messagesDispatcher,
    sdk
  });
  const scrollToMessage = useScrollToMessage({
    setInitialTimeStamp,
    setAnimatedMessageId,
    allMessages,
    scrollRef
  }, {
    logger
  });

  // onScrollDownCallback is added for navigation to different timestamps on messageSearch
  // hasMorePrev, onScrollCallback -> scroll up(default behavior)
  // hasMoreNext, onScrollDownCallback -> scroll down
  const onScrollDownCallback = useScrollDownCallback({
    currentGroupChannel,
    latestMessageTimeStamp,
    userFilledMessageListQuery,
    hasMoreNext,
    replyType,
    isVoiceMessageEnabled
  }, {
    logger,
    messagesDispatcher,
    sdk
  });
  const toggleReaction = useToggleReactionCallback({
    currentGroupChannel
  }, {
    logger
  });

  // to create message-datasource
  // this hook sets currentGroupChannel asynchronously
  useSetChannel({
    channelUrl,
    sdkInit,
    disableMarkAsRead
  }, {
    messagesDispatcher,
    sdk,
    logger,
    markAsReadScheduler
  });

  // to set quote message as null
  useEffect(() => {
    setQuoteMessage(null);
  }, [channelUrl]);

  // Hook to handle ChannelEvents and send values to useReducer using messagesDispatcher
  useHandleChannelEvents({
    currentGroupChannel,
    sdkInit,
    currentUserId: userId,
    disableMarkAsRead
  }, {
    messagesDispatcher,
    sdk,
    logger,
    scrollRef,
    setQuoteMessage
  });

  // hook that fetches messages when channel changes
  // to be clear here useGetChannel sets currentGroupChannel
  // and useInitialMessagesFetch executes when currentGroupChannel changes
  // p.s This one executes on initialTimeStamp change too
  useInitialMessagesFetch({
    currentGroupChannel,
    userFilledMessageListQuery,
    initialTimeStamp,
    latestMessageTimeStamp,
    replyType,
    isVoiceMessageEnabled
  }, {
    logger,
    scrollRef,
    messagesDispatcher
  });

  // handles API calls from withSendbird
  useEffect(() => {
    const subscriber = pubSubHandler({
      channelUrl,
      pubSub,
      dispatcher: messagesDispatcher,
      scrollRef
    });
    return () => {
      pubSubHandleRemover(subscriber);
    };
  }, [channelUrl, sdkInit]);

  // handling connection breaks
  useHandleReconnect({
    isOnline,
    replyType,
    disableMarkAsRead
  }, {
    logger,
    sdk,
    scrollRef,
    currentGroupChannel,
    messagesDispatcher,
    userFilledMessageListQuery,
    markAsReadScheduler
  });

  // callbacks for Message CURD actions
  const deleteMessage = useDeleteMessageCallback({
    currentGroupChannel,
    messagesDispatcher
  }, {
    logger
  });
  const updateMessage = useUpdateMessageCallback({
    currentGroupChannel,
    messagesDispatcher,
    onBeforeUpdateUserMessage,
    isMentionEnabled
  }, {
    logger,
    pubSub
  });
  const resendMessage = useResendMessageCallback({
    currentGroupChannel,
    messagesDispatcher
  }, {
    logger
  });
  const [messageInputRef, sendMessage] = useSendMessageCallback({
    currentGroupChannel,
    onBeforeSendUserMessage,
    isMentionEnabled
  }, {
    logger,
    pubSub,
    scrollRef,
    messagesDispatcher
  });
  const [sendFileMessage] = useSendFileMessageCallback({
    currentGroupChannel,
    onBeforeSendFileMessage,
    imageCompression
  }, {
    logger,
    pubSub,
    scrollRef,
    messagesDispatcher
  });
  const [sendVoiceMessage] = useSendVoiceMessageCallback({
    currentGroupChannel,
    onBeforeSendVoiceMessage
  }, {
    logger,
    pubSub,
    scrollRef,
    messagesDispatcher
  });
  return /*#__PURE__*/React__default.createElement(ChannelContext.Provider, {
    value: {
      // props
      channelUrl,
      isReactionEnabled: usingReaction,
      isMessageGroupingEnabled,
      showSearchIcon: showSearchIcon !== null && showSearchIcon !== void 0 ? showSearchIcon : globalConfigs.showSearchIcon,
      highlightedMessage,
      startingPoint,
      onBeforeSendUserMessage,
      onBeforeSendFileMessage,
      onBeforeUpdateUserMessage,
      onChatHeaderActionClick,
      onSearchClick,
      onBackClick,
      replyType,
      threadReplySelectType: (_ref = threadReplySelectType !== null && threadReplySelectType !== void 0 ? threadReplySelectType : getCaseResolvedThreadReplySelectType(groupChannel.threadReplySelectType).upperCase) !== null && _ref !== void 0 ? _ref : ThreadReplySelectType.THREAD,
      queries,
      filterMessageList,
      disableMarkAsRead,
      onReplyInThread,
      onQuoteMessageClick,
      onMessageAnimated,
      onMessageHighlighted,
      // messagesStore
      allMessages,
      loading,
      initialized,
      unreadSince,
      isInvalid,
      currentGroupChannel,
      hasMorePrev,
      hasMoreNext,
      oldestMessageTimeStamp,
      latestMessageTimeStamp,
      emojiContainer,
      readStatus,
      // utils
      scrollToMessage,
      quoteMessage,
      setQuoteMessage,
      deleteMessage,
      updateMessage,
      resendMessage,
      messageInputRef,
      sendMessage,
      sendFileMessage,
      sendVoiceMessage,
      initialTimeStamp,
      messageActionTypes,
      messagesDispatcher,
      setInitialTimeStamp,
      setAnimatedMessageId,
      setHighLightedMessageId,
      animatedMessageId,
      highLightedMessageId,
      nicknamesMap,
      emojiAllMap,
      onScrollCallback,
      onScrollDownCallback,
      scrollRef,
      scrollBehavior,
      toggleReaction
    }
  }, /*#__PURE__*/React__default.createElement(UserProfileProvider, {
    disableUserProfile: (_props$disableUserPro = props === null || props === void 0 ? void 0 : props.disableUserProfile) !== null && _props$disableUserPro !== void 0 ? _props$disableUserPro : config === null || config === void 0 ? void 0 : config.disableUserProfile,
    renderUserProfile: props === null || props === void 0 ? void 0 : props.renderUserProfile,
    onUserProfileMessage: onUserProfileMessage
  }, children));
};
const useChannelContext = () => React__default.useContext(ChannelContext);

export { ChannelProvider as C, isDisabledBecauseFrozen as a, isDisabledBecauseMuted as b, compareMessagesForGrouping as c, isOperator as d, getIsReactionEnabled as g, isAboutSame as i, useChannelContext as u };
//# sourceMappingURL=ChannelProvider-498954bf.js.map
