{"version":3,"sources":["../src/utils.ts","../src/Broadcast.ts","../src/fetch.ts","../src/MessageClient.ts","../src/Connection.ts","../src/error.ts","../src/Conversation.ts","../src/ChatClient.ts"],"sourcesContent":["import moment from 'moment';\r\n\r\nimport { Conversation, StringOrNumber, Participant, ParticipantListInfo, Message, MessageStates, UserMeta } from \"./types\";\r\n\r\nfunction murmurHash3_x64_64(str: string, seed = 0) {\r\n  let h1 = BigInt(seed);\r\n  let h2 = BigInt(seed);\r\n  const c1 = BigInt(\"0x87c37b91114253d5\");\r\n  const c2 = BigInt(\"0x4cf5ad432745937f\");\r\n\r\n  let length = str.length;\r\n  const remainder = length & 15; // length % 16\r\n  const bytes = length - remainder;\r\n\r\n  for (let i = 0; i < bytes; i += 16) {\r\n    let k1 =\r\n      BigInt(str.charCodeAt(i)) |\r\n      (BigInt(str.charCodeAt(i + 1)) << BigInt(8)) |\r\n      (BigInt(str.charCodeAt(i + 2)) << BigInt(16)) |\r\n      (BigInt(str.charCodeAt(i + 3)) << BigInt(24)) |\r\n      (BigInt(str.charCodeAt(i + 4)) << BigInt(32)) |\r\n      (BigInt(str.charCodeAt(i + 5)) << BigInt(40)) |\r\n      (BigInt(str.charCodeAt(i + 6)) << BigInt(48)) |\r\n      (BigInt(str.charCodeAt(i + 7)) << BigInt(56));\r\n\r\n    let k2 =\r\n      BigInt(str.charCodeAt(i + 8)) |\r\n      (BigInt(str.charCodeAt(i + 9)) << BigInt(8)) |\r\n      (BigInt(str.charCodeAt(i + 10)) << BigInt(16)) |\r\n      (BigInt(str.charCodeAt(i + 11)) << BigInt(24)) |\r\n      (BigInt(str.charCodeAt(i + 12)) << BigInt(32)) |\r\n      (BigInt(str.charCodeAt(i + 13)) << BigInt(40)) |\r\n      (BigInt(str.charCodeAt(i + 14)) << BigInt(48)) |\r\n      (BigInt(str.charCodeAt(i + 15)) << BigInt(56));\r\n\r\n    k1 = k1 * c1;\r\n    k1 = (k1 << BigInt(31)) | (k1 >> BigInt(33));\r\n    k1 = k1 * c2;\r\n    h1 ^= k1;\r\n\r\n    h1 = (h1 << BigInt(27)) | (h1 >> BigInt(37));\r\n    h1 = h1 + h2;\r\n    h1 = h1 * BigInt(5) + BigInt(\"0x52dce729\");\r\n\r\n    k2 = k2 * c2;\r\n    k2 = (k2 << BigInt(33)) | (k2 >> BigInt(31));\r\n    k2 = k2 * c1;\r\n    h2 ^= k2;\r\n\r\n    h2 = (h2 << BigInt(31)) | (h2 >> BigInt(33));\r\n    h2 = h1 + h2;\r\n    h2 = h2 * BigInt(5) + BigInt(\"0x38495ab5\");\r\n  }\r\n\r\n  let k1 = BigInt(0);\r\n  let k2 = BigInt(0);\r\n\r\n  switch (remainder) {\r\n    case 15:\r\n      k2 ^= BigInt(str.charCodeAt(bytes + 14)) << BigInt(48);\r\n    case 14:\r\n      k2 ^= BigInt(str.charCodeAt(bytes + 13)) << BigInt(40);\r\n    case 13:\r\n      k2 ^= BigInt(str.charCodeAt(bytes + 12)) << BigInt(32);\r\n    case 12:\r\n      k2 ^= BigInt(str.charCodeAt(bytes + 11)) << BigInt(24);\r\n    case 11:\r\n      k2 ^= BigInt(str.charCodeAt(bytes + 10)) << BigInt(16);\r\n    case 10:\r\n      k2 ^= BigInt(str.charCodeAt(bytes + 9)) << BigInt(8);\r\n    case 9:\r\n      k2 ^= BigInt(str.charCodeAt(bytes + 8));\r\n      k2 = k2 * c2;\r\n      k2 = (k2 << BigInt(33)) | (k2 >> BigInt(31));\r\n      k2 = k2 * c1;\r\n      h2 ^= k2;\r\n    case 8:\r\n      k1 ^= BigInt(str.charCodeAt(bytes + 7)) << BigInt(56);\r\n    case 7:\r\n      k1 ^= BigInt(str.charCodeAt(bytes + 6)) << BigInt(48);\r\n    case 6:\r\n      k1 ^= BigInt(str.charCodeAt(bytes + 5)) << BigInt(40);\r\n    case 5:\r\n      k1 ^= BigInt(str.charCodeAt(bytes + 4)) << BigInt(32);\r\n    case 4:\r\n      k1 ^= BigInt(str.charCodeAt(bytes + 3)) << BigInt(24);\r\n    case 3:\r\n      k1 ^= BigInt(str.charCodeAt(bytes + 2)) << BigInt(16);\r\n    case 2:\r\n      k1 ^= BigInt(str.charCodeAt(bytes + 1)) << BigInt(8);\r\n    case 1:\r\n      k1 ^= BigInt(str.charCodeAt(bytes));\r\n      k1 = k1 * c1;\r\n      k1 = (k1 << BigInt(31)) | (k1 >> BigInt(33));\r\n      k1 = k1 * c2;\r\n      h1 ^= k1;\r\n  }\r\n\r\n  h1 ^= BigInt(length);\r\n  h2 ^= BigInt(length);\r\n\r\n  h1 += h2;\r\n  h2 += h1;\r\n\r\n  h1 ^= h1 >> BigInt(33);\r\n  h1 = h1 * BigInt(\"0xff51afd7ed558ccd\");\r\n  h1 ^= h1 >> BigInt(33);\r\n  h1 = h1 * BigInt(\"0xc4ceb9fe1a85ec53\");\r\n  h1 ^= h1 >> BigInt(33);\r\n\r\n  h2 ^= h2 >> BigInt(33);\r\n  h2 = h2 * BigInt(\"0xff51afd7ed558ccd\");\r\n  h2 ^= h2 >> BigInt(33);\r\n  h2 = h2 * BigInt(\"0xc4ceb9fe1a85ec53\");\r\n  h2 ^= h2 >> BigInt(33);\r\n\r\n  h1 += h2;\r\n  h2 += h1;\r\n\r\n  // Combine h1 and h2 to return a 64-bit hash\r\n  return (h1 & BigInt(\"0xFFFFFFFFFFFFFFFF\")).toString(16);\r\n}\r\n\r\n// Updated generateConversationId using MurmurHash3 x64 (64-bit)\r\nexport function generateConversationId(str1: string, str2: string, projectId: string) {\r\n  // Sort the strings alphabetically to ensure consistency\r\n  const sortedStrings = [str1, str2].sort();\r\n  // Concatenate the sorted strings with a delimiter\r\n  const combinedString = sortedStrings.join(\"_\");\r\n  // Generate a 64-bit hash of the combined string using MurmurHash3 x64\r\n  const hash = murmurHash3_x64_64(`${projectId}:${combinedString}`);\r\n  // Return the hash as the unique ID\r\n  return hash;\r\n}\r\n\r\nexport const generateId = () => {\r\n    let uuid = '';\r\n    const characters = 'abcdef0123456789';\r\n    for (let i = 0; i < 32; i++) {\r\n      const randomNumber = Math.floor(Math.random() * characters.length);\r\n      const character = characters.charAt(randomNumber);\r\n      if (i === 8 || i === 12 || i === 16 || i === 20) {\r\n        uuid += '-';\r\n      }\r\n      uuid += character;\r\n    }\r\n    return uuid;\r\n}\r\n\r\n\r\nexport const getUserInfoWithId = (userId: string, participantList: ParticipantListInfo[]): {\r\n  presentUser: UserMeta | undefined,\r\n  receivingUser: UserMeta | undefined,\r\n} => {\r\n  let presentUser = participantList.find(participant => participant.participantId === userId);\r\n  let otherParticipants = participantList.filter(participant => participant.participantId !== userId)\r\n  return { presentUser: presentUser?.participantDetails, receivingUser: otherParticipants[0]?.participantDetails };\r\n};\r\n\r\nexport const truncate = (str: string, len: number) => {\r\n  return str.length > len ? str.substring(0, len)+'...' : str;\r\n}\r\n\r\nexport const getConversationTitle = (userId: string, converstaion: Conversation) => {\r\n  if(converstaion.conversationType === 'private-chat'){\r\n    const userInfos = getUserInfoWithId(userId, converstaion.participantList);\r\n\r\n    const firstname = userInfos.receivingUser?.firstname\r\n    const username = userInfos.receivingUser?.username\r\n    return firstname? firstname : username\r\n  }\r\n  if(converstaion.conversationType === 'group-chat') {\r\n    return converstaion.groupMeta?.groupName || 'no-groupname'\r\n  }\r\n}\r\n\r\nexport const getUsernameInitials = (username: string) =>{\r\n  return username.substring(0, 1)\r\n}\r\n\r\nexport function formatMessageTime(time: Date | string) {\r\n  return moment(new Date(time)).format(\"hh:mm a\");\r\n}\r\n\r\nexport function formatConversationTime(time: Date | string) {\r\n  const now = moment();\r\n  const then = moment(time);\r\n  const duration = moment.duration(now.diff(then));\r\n\r\n  // Get the largest unit\r\n  const years = Math.floor(duration.asYears());\r\n  if (years > 0) return years + 'yr';\r\n\r\n  const months = Math.floor(duration.asMonths());\r\n  if (months > 0) return months + 'mo';\r\n\r\n  const weeks = Math.floor(duration.asWeeks());\r\n  if (weeks > 0) return weeks + 'w';\r\n\r\n  const days = Math.floor(duration.asDays());\r\n  if (days > 0) return days + 'd';\r\n\r\n  const hours = Math.floor(duration.asHours());\r\n  if (hours > 0) return hours + 'h';\r\n\r\n  const minutes = Math.floor(duration.asMinutes());\r\n  if (minutes > 0) return minutes + 'm';\r\n\r\n  // If duration is less than 1 minute\r\n  return 'Just now';\r\n}\r\n\r\nexport const generateFillerTimestamps = () => {\r\n  return {\r\n    createdAt: new Date(),\r\n    updatedAt: new Date(),\r\n  }\r\n}\r\n\r\nexport const getUnreadMessageIds = (conversation: Conversation, userId: string) => {\r\n  var ids: string[] = []\r\n  conversation.messages.map(m => {\r\n    if (m.messageState === MessageStates.SENT && m.from !== userId) {\r\n      ids.push(m.messageId)\r\n    }\r\n  })\r\n  return ids\r\n}\r\n\r\nexport const getQuotedMessage = (messageId: string, messages: Message[]) => {\r\n  const message = messages.find(msg => msg.messageId === messageId)\r\n  return message\r\n}\r\n","import Connection from \"./Connection\";\r\nimport { Errors } from \"./error\";\r\nimport { Events } from \"./events\";\r\nimport {\r\n  AttachmentTypes,\r\n  BroadcastListMeta,\r\n  Conversation,\r\n  ConversationListItem,\r\n  ConversationType,\r\n  GroupChatMeta,\r\n  Message,\r\n  MessageStates,\r\n  Participant,\r\n  Prettify,\r\n  SendGroupMessageGenerics,\r\n  SendMessageGenerics,\r\n  ServerActions,\r\n  UserMeta,\r\n} from \"./types\";\r\nimport {\r\n  generateConversationId,\r\n  generateFillerTimestamps,\r\n  generateId,\r\n} from \"./utils\";\r\n\r\nlet userMetaSample = {\r\n  id: \"\",\r\n  username: \"\",\r\n  email: \"\",\r\n  firstname: \"\",\r\n  lastname: \"\",\r\n  profileImgUrl: \"\",\r\n  phone: \"\",\r\n  profileBannerUrl: \"\",\r\n  custom: {},\r\n};\r\nexport default class BroadcastList {\r\n  private static conversation: BroadcastList | null = null;\r\n  private connection: Connection;\r\n  private participants: UserMeta[];\r\n\r\n  constructor(connection: Connection, participants: UserMeta[]) {\r\n    this.connection = connection;\r\n    this.participants = participants;\r\n  }\r\n\r\n  static getInstance(\r\n    connection: Connection,\r\n    participants: UserMeta[]\r\n  ): BroadcastList {\r\n    if (BroadcastList.conversation) {\r\n      return BroadcastList.conversation;\r\n    }\r\n    BroadcastList.conversation = new BroadcastList(connection, participants);\r\n    return BroadcastList.conversation;\r\n  }\r\n\r\n  private generateConversation(\r\n    name: string,\r\n    conversationId: string\r\n  ): Conversation & { name: string } {\r\n    const timeStamps = generateFillerTimestamps();\r\n    const participantIds = this.participants.map((p) => p.uid);\r\n    const senderObject = {\r\n      id: generateId(),\r\n      uid: this.connection.userMeta.uid,\r\n      participantId: this.connection.userMeta.uid,\r\n      participantDetails: {\r\n        ...this.connection.userMeta,\r\n        ...timeStamps,\r\n      },\r\n      ...timeStamps,\r\n    };\r\n\r\n    const updatedParticipantList = this.participants.map((participant) => ({\r\n      id: generateId(),\r\n      uid: participant.uid,\r\n      participantId: participant.uid,\r\n      participantDetails: {\r\n        ...participant,\r\n        ...timeStamps,\r\n      },\r\n      ...timeStamps,\r\n    }));\r\n\r\n    const participantList = [senderObject, ...updatedParticipantList];\r\n\r\n    return {\r\n      name,\r\n      participants: [this.connection.userMeta.uid, ...participantIds],\r\n      admins: [this.connection.userMeta.uid],\r\n      conversationId,\r\n      messages: [],\r\n      conversationType: \"broadcast-chat\",\r\n      participantList,\r\n      meta: null,\r\n      groupMeta: null,\r\n      ...timeStamps,\r\n    };\r\n  }\r\n\r\n  create(name: string = `${this.participants.length} Recipients`) {\r\n    try {\r\n      if (!this.connection) {\r\n        throw new Error(\"Inialize uesr before calling method\");\r\n      }\r\n      const conversationId = generateId();\r\n      const newConveration = this.generateConversation(name, conversationId);\r\n      const socketMessage = {\r\n        action: ServerActions.CREATE_BROADCAST_LIST,\r\n        message: {\r\n          conversationId,\r\n          name: name,\r\n          participants: this.participants,\r\n          token: this.connection.wsAccessConfig.token,\r\n          user: this.connection.userMeta,\r\n        },\r\n      };\r\n      this.connection.socket.send(JSON.stringify(socketMessage));\r\n      this.connection.broadcastListMeta[conversationId] = {\r\n        conversation: newConveration,\r\n        lastMessage: null,\r\n        unread: [],\r\n      };\r\n      this.reset();\r\n      this.connection.emit(Events.BROADCAST_LIST_META_CHANGED, {\r\n        broadcastListMeta: this.connection.broadcastListMeta,\r\n      });\r\n      return {\r\n        [conversationId]: {\r\n          conversation: newConveration,\r\n          lastMessage: null,\r\n          unread: [],\r\n        },\r\n      };\r\n    } catch (error) {\r\n      if(error instanceof Error){\r\n        console.error(error.message);\r\n      }\r\n    }\r\n  }\r\n\r\n  reset() {\r\n    BroadcastList.conversation = null;\r\n  }\r\n}\r\n","import axios, { AxiosResponse } from \"axios\";\r\nimport { MediaType, Prettify, UploadContent } from \"./types\";\r\n\r\nlet API = \"https://api.softchatjs.com\";\r\n\r\nenum ENDPOINTS {\r\n  CONVERSATIONS = \"/conversations\",\r\n  CONVERSATION = \"/conversation\",\r\n  MESSAGES = \"/messages\",\r\n  UPLOAD = \"/upload\",\r\n  UPLOAD_ATTACHMENT = \"/upload-attachment\",\r\n  CREATE_SESSION = \"/auth/session\",\r\n  EMOJIS = \"/gifs/trending\",\r\n  GET_PRESIGNED_URL = \"/presigned-url\",\r\n  BROADCAST_LIST = \"/broadcastlist\",\r\n  BROADCAST_LISTS = \"/broadcastlists\",\r\n}\r\n\r\ntype Payload = {\r\n  endpoint: string;\r\n  body: Object;\r\n  method: \"GET\" | \"POST\" | \"PUT\";\r\n  token?: string;\r\n  headers?: Record<string, string>;\r\n};\r\n\r\nconst chatApi = async <R>(payload: Payload): Promise<APIResponse<R>> => {\r\n  try {\r\n    const res: AxiosResponse<R> = await axios({\r\n      url: payload.endpoint,\r\n      method: payload.method,\r\n      headers: {\r\n        \"Cache-Control\": \"no-cache\",\r\n        accessToken: payload.token || \"\",\r\n        \"Content-Type\": \"application/json\",\r\n        ...payload.headers,\r\n      },\r\n      data: payload.method === \"POST\" ? payload.body : undefined,\r\n      responseType: \"json\",\r\n      timeout: 30000,\r\n    });\r\n    const response = res.data;\r\n    if (typeof response === \"object\" && response && \"success\" in response) {\r\n      return response as unknown as APIResponse<R>;\r\n    }\r\n    return { ...response, success: false } as unknown as APIResponse<R>;\r\n  } catch (error) {\r\n    console.log(error, \"fetch error\");\r\n    if (axios.isAxiosError(error) && error.response) {\r\n      throw new Error(`HTTP error! Status: ${error.response.status}`);\r\n    }\r\n    throw new Error(\"An unknown error occurred.\");\r\n  }\r\n};\r\n\r\ntype APIResponse<R> = {\r\n  success: boolean;\r\n  data: R;\r\n  message: string;\r\n};\r\n\r\nexport async function CREATE_SESSION<Response>({\r\n  userId,\r\n  subId,\r\n  projectId,\r\n}: {\r\n  userId: string;\r\n  subId: string;\r\n  projectId: string;\r\n}): Promise<APIResponse<Response>> {\r\n  return await chatApi<Response>({\r\n    endpoint: `${API}${ENDPOINTS.CREATE_SESSION}`,\r\n    body: { userId, projectId, subId },\r\n    method: \"POST\",\r\n    // headers: { \"x-api-key\": apiKey },\r\n  });\r\n}\r\n\r\nexport async function GET_CONVERSATIONS<Response>(\r\n  token: string | undefined,\r\n): Promise<APIResponse<Response>> {\r\n  return await chatApi<Response>({\r\n    endpoint: `${API}${ENDPOINTS.CONVERSATIONS}`,\r\n    body: {},\r\n    method: \"GET\",\r\n    token,\r\n  });\r\n}\r\n\r\nexport async function GET_CONVERSATION<Response>(\r\n  token: string | undefined, conversationId: string\r\n): Promise<APIResponse<Response>> {\r\n  return await chatApi<Response>({\r\n    endpoint: `${API}${ENDPOINTS.CONVERSATION}/${conversationId}`,\r\n    body: {},\r\n    method: \"GET\",\r\n    token,\r\n  });\r\n}\r\n\r\nexport async function GET_BROADCASTLISTS<Response>(\r\n  token: string | undefined\r\n): Promise<APIResponse<Response>> {\r\n  return await chatApi<Response>({\r\n    endpoint: `${API}${ENDPOINTS.BROADCAST_LISTS}`,\r\n    body: {},\r\n    method: \"GET\",\r\n    token,\r\n  });\r\n}\r\n\r\nexport async function GET_MESSAGES<Response>(\r\n  token: string | undefined,\r\n  conversationId: string,\r\n  page?: number\r\n): Promise<APIResponse<Response>> {\r\n  return await chatApi<Response>({\r\n    endpoint: `${API}${ENDPOINTS.MESSAGES}/${conversationId}${page ? \"?page=\" + page : \"\"}`,\r\n    body: {},\r\n    method: \"GET\",\r\n    token,\r\n  });\r\n}\r\n\r\nexport async function GET_BROADCAST_LIST_MESSAGES<Response>(\r\n  token: string | undefined,\r\n  broadcastListId: string,\r\n  page?: number\r\n): Promise<APIResponse<Response>> {\r\n  return await chatApi<Response>({\r\n    endpoint: `${API}${ENDPOINTS.BROADCAST_LIST}/messages/${broadcastListId}${page ? \"?page=\" + page : \"\"}`,\r\n    body: {},\r\n    method: \"GET\",\r\n    token,\r\n  });\r\n}\r\n\r\nexport async function GET_EMOJIS<Response>(\r\n  token: string | undefined\r\n): Promise<APIResponse<Response>> {\r\n  return await chatApi<Response>({\r\n    endpoint: `${API}${ENDPOINTS.EMOJIS}`,\r\n    body: {},\r\n    method: \"GET\",\r\n    token,\r\n  });\r\n}\r\n\r\nexport async function UPLOAD_MEDIA<Response>(\r\n  token: string,\r\n  data: Prettify<UploadContent>\r\n): Promise<APIResponse<Response>> {\r\n  return await chatApi<Response>({\r\n    endpoint: `${API}${ENDPOINTS.UPLOAD}`,\r\n    body: data,\r\n    method: \"POST\",\r\n    token,\r\n  });\r\n}\r\n\r\nexport async function GET_PRESIGNED_URL<Response>(\r\n  token: string,\r\n  data: Prettify<UploadContent & { mediaType: string, uid: string, ext: string }>\r\n): Promise<APIResponse<Response>> {\r\n  return await chatApi<Response>({\r\n    endpoint: `${API}${ENDPOINTS.GET_PRESIGNED_URL}`,\r\n    body: data,\r\n    method: \"POST\",\r\n    token,\r\n  });\r\n}\r\n\r\nexport async function UPLOAD_ATTACHMENT<Response>(\r\n  token: string,\r\n  data: any\r\n): Promise<APIResponse<Response>> {\r\n  return await chatApi<Response>({\r\n    endpoint: `${API}${ENDPOINTS.UPLOAD_ATTACHMENT}`,\r\n    body: data,\r\n    method: \"POST\",\r\n    token,\r\n    headers: { \"Content-Type\": \"multipart/form-data\" },\r\n  });\r\n}\r\n","import Connection from \"./Connection\";\r\nimport {\r\n  ClientActions,\r\n  Conversation,\r\n  ConversationListItem,\r\n  ConversationType,\r\n  ConversationWithTypingIndicator,\r\n  DeletedMessage,\r\n  EditedMessage,\r\n  MediaType,\r\n  Message,\r\n  MessageStates,\r\n  Prettify,\r\n  Reaction,\r\n  ReadMessages,\r\n  Screens,\r\n  SendMessageGenerics,\r\n  ServerActions,\r\n  UserMeta,\r\n  WsPayLoad,\r\n} from \"./types\";\r\nimport {\r\n  generateConversationId,\r\n  generateFillerTimestamps,\r\n  generateId,\r\n} from \"./utils\";\r\nimport { Events } from \"./events\";\r\nimport {\r\n  GET_BROADCAST_LIST_MESSAGES,\r\n  GET_CONVERSATION,\r\n  GET_EMOJIS,\r\n  GET_MESSAGES,\r\n  GET_PRESIGNED_URL,\r\n  UPLOAD_ATTACHMENT,\r\n  UPLOAD_MEDIA,\r\n} from \"./fetch\";\r\nimport { Emoticon } from \"./emoticon.type\";\r\nimport moment from \"moment\";\r\nimport { Readable } from \"stream\";\r\n\r\nlet CLEAR_UNREAD_TIMEOUT = 1000;\r\n\r\nexport default class MessageClient {\r\n  private static message_client: MessageClient;\r\n  private connection: Connection;\r\n  // private currentConversationId: string;\r\n  private screen: Screens;\r\n  private idleTimers: { [key: string]: NodeJS.Timeout | undefined };\r\n\r\n  constructor(connection: Connection, conversationId: string) {\r\n    this.connection = connection;\r\n    this.idleTimers = {};\r\n    // this.connection.activeConversationId = conversationId;\r\n    this.screen = Screens.CONVERSATIONS;\r\n  }\r\n\r\n  static getInstace(connection: Connection, conversationId: string) {\r\n    if (MessageClient.message_client) {\r\n      if (conversationId) {\r\n        MessageClient.message_client.connection.activeConversationId =\r\n          conversationId;\r\n      }\r\n      return MessageClient.message_client;\r\n    } else {\r\n      MessageClient.message_client = new MessageClient(\r\n        connection,\r\n        conversationId\r\n      );\r\n      return MessageClient.message_client;\r\n    }\r\n  }\r\n\r\n  private getPublicMethods() {\r\n    return {\r\n      getMessages: this.getMessages.bind(this),\r\n      sendMessage: this.sendMessage.bind(this),\r\n      editMessage: this.editMessage.bind(this),\r\n      sendTypingNotification: this.sendTypingNotification.bind(this),\r\n      reactToMessage: this.reactToMessage.bind(this),\r\n      uploadAttachment: this.uploadAttachment.bind(this),\r\n    };\r\n  }\r\n\r\n  private getConversationType(conversationId?: string) {\r\n    // const conversationMeta = this.connection.conversationListMeta[conversationId? conversationId : this.connection.activeConversationId];\r\n    try {\r\n      const conversationMeta =\r\n        this.connection.conversationListMeta[\r\n          conversationId ? conversationId : this.connection.activeConversationId\r\n        ];\r\n      return conversationMeta.conversation.conversationType;\r\n    } catch (error) {\r\n      return \"private-chat\";\r\n    }\r\n  }\r\n\r\n  // removes the last item in the list and adds a new one to the end keeping the original length\r\n  private rotateAndInsertMessageList = (\r\n    messageList: Array<Message>,\r\n    message: Message\r\n  ) => {\r\n    var list = [...messageList];\r\n    if (messageList.length >= 25) {\r\n      var list = [...messageList];\r\n      list.unshift();\r\n      list.push(message);\r\n      return list;\r\n    }\r\n    list.push(message);\r\n    return list;\r\n  };\r\n\r\n  private _createMessage(newMessage: Message) {\r\n    try {\r\n      if (newMessage) {\r\n        const socketMessage = {\r\n          action: ServerActions.SEND_MESSAGE,\r\n          message: {\r\n            messageId: newMessage.messageId,\r\n            from: this.connection.userMeta.uid,\r\n            to: newMessage.to,\r\n            conversationType: this.getConversationType(),\r\n            message: { ...newMessage, messageState: MessageStates.SENT },\r\n            user: this.connection.userMeta,\r\n            token: this.connection.wsAccessConfig.token,\r\n          },\r\n        };\r\n        this.connection.emit(Events.NEW_MESSAGE, {\r\n          message: {\r\n            ...newMessage,\r\n            reactions: [],\r\n            messageState: MessageStates.LOADING,\r\n          },\r\n        });\r\n        if (\r\n          this.connection.socket &&\r\n          this.connection.socket?.readyState === WebSocket.OPEN\r\n        ) {\r\n          this.connection.socket.send(JSON.stringify(socketMessage));\r\n          this.connection.emit(Events.EDITED_MESSAGE, {\r\n            message: {\r\n              ...newMessage,\r\n              reactions: [],\r\n              messageState: MessageStates.SENT,\r\n            },\r\n          });\r\n          var conversationMeta =\r\n            this.connection.conversationListMeta[newMessage.conversationId];\r\n\r\n          var updatedMessages = this.rotateAndInsertMessageList(\r\n            conversationMeta.conversation.messages,\r\n            {\r\n              ...newMessage,\r\n              reactions: [],\r\n              messageState: MessageStates.SENT,\r\n            }\r\n          );\r\n          const unread = conversationMeta.unread;\r\n          this.connection.conversationListMeta[newMessage.conversationId] = {\r\n            conversation: {\r\n              ...conversationMeta.conversation,\r\n              messages: updatedMessages,\r\n            },\r\n            lastMessage: {\r\n              ...newMessage,\r\n            },\r\n            unread: unread,\r\n          };\r\n          this.connection.emit(Events.CONVERSATION_LIST_META_CHANGED, {\r\n            conversationListMeta: this.connection.conversationListMeta,\r\n          });\r\n        } else {\r\n          this.connection.emit(Events.EDITED_MESSAGE, {\r\n            message: {\r\n              ...newMessage,\r\n              reactions: [],\r\n              messageState: MessageStates.FAILED,\r\n            },\r\n          });\r\n          this.connection.conversationListMeta[newMessage.conversationId] = {\r\n            conversation:\r\n              this.connection.conversationListMeta[newMessage.conversationId]\r\n                .conversation,\r\n            lastMessage: {\r\n              ...newMessage,\r\n              messageState: MessageStates.FAILED,\r\n            },\r\n            unread: [],\r\n          };\r\n          this.connection.emit(Events.CONVERSATION_LIST_META_CHANGED, {\r\n            conversationListMeta: this.connection.conversationListMeta,\r\n          });\r\n        }\r\n      }\r\n    } catch (error) {\r\n      if (error instanceof Error) {\r\n        console.error(error);\r\n        this.connection.emit(Events.DELETED_MESSAGE, {\r\n          message: {\r\n            ...newMessage,\r\n            reactions: [],\r\n            messageState: MessageStates.FAILED,\r\n          },\r\n        });\r\n      }\r\n    }\r\n  }\r\n\r\n  private editConversationListMetaMessage({ isBroadcast, updatedMessage } : { isBroadcast: boolean, updatedMessage: any }) {\r\n    var conversationMeta = isBroadcast? this.connection.broadcastListMeta[updatedMessage.conversationId] : this.connection.conversationListMeta[updatedMessage.conversationId];\r\n    var messageId = updatedMessage.messageId;\r\n    if (conversationMeta) {\r\n      // const socketMessage = {\r\n      //   action: ServerActions.EDIT_MESSAGE,\r\n      //   message: {\r\n      //     ...updatedMessage,\r\n      //     token: this.connection.wsAccessConfig.token,\r\n      //   },\r\n      // };\r\n      // this.connection.socket.send(JSON.stringify(socketMessage));\r\n      var prevMessage = conversationMeta.conversation.messages.find(\r\n        (m) => m.messageId === messageId\r\n      );\r\n      if (prevMessage) {\r\n        var editedMessage = {\r\n          ...prevMessage,\r\n          message: updatedMessage.textMessage,\r\n          lastEdited: new Date(),\r\n        };\r\n        var updatedMessageList = conversationMeta.conversation.messages.map(\r\n          (m) => {\r\n            if (m.messageId === messageId) {\r\n              return editedMessage;\r\n            }\r\n            return m;\r\n          }\r\n        );\r\n        \r\n        if(isBroadcast){\r\n          this.connection.broadcastListMeta[updatedMessage.conversationId] = {\r\n            conversation: {\r\n              ...conversationMeta.conversation,\r\n              messages: updatedMessageList,\r\n            },\r\n            lastMessage: null,\r\n            unread: [],\r\n          };\r\n          this.connection.emit(Events.BROADCAST_LIST_META_CHANGED, {\r\n            broadcastListMeta: this.connection.broadcastListMeta,\r\n          });\r\n        }else{\r\n          this.connection.conversationListMeta[updatedMessage.conversationId] = {\r\n            conversation: {\r\n              ...conversationMeta.conversation,\r\n              messages: updatedMessageList,\r\n            },\r\n            lastMessage: { ...editedMessage },\r\n            unread: conversationMeta.unread,\r\n          };\r\n          this.connection.emit(Events.CONVERSATION_LIST_META_CHANGED, {\r\n            conversationListMeta: this.connection.conversationListMeta,\r\n          });\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  private _editMessage(message: EditedMessage) {\r\n    try {\r\n      if (message) {\r\n        let updatedMessage = {\r\n          ...message,\r\n          message: message.textMessage,\r\n          lastEdited: new Date(),\r\n        };\r\n        this.connection.emit(Events.EDITED_MESSAGE, {\r\n          message: updatedMessage,\r\n        });\r\n        this.editConversationListMetaMessage({\r\n          isBroadcast: false, \r\n          updatedMessage \r\n        });\r\n\r\n        // update both lists !!might need improvement, maybe go back to using a single list.\r\n        this.editConversationListMetaMessage({\r\n          isBroadcast: true, \r\n          updatedMessage \r\n        });\r\n       \r\n        if(this.connection.socket){\r\n          const socketMessage = {\r\n            action: ServerActions.EDIT_MESSAGE,\r\n            message: {\r\n              ...updatedMessage,\r\n              token: this.connection.wsAccessConfig.token,\r\n              isBroadcast: message.isBroadcast,\r\n              user: this.connection.userMeta\r\n            },\r\n          };\r\n          this.connection.socket.send(JSON.stringify(socketMessage));\r\n        }\r\n        // if(this.connection.socket){\r\n        //   const socketMessage = {\r\n        //     action: ServerActions.EDIT_MESSAGE,\r\n        //     message: {\r\n        //       ...updatedMessage,\r\n        //       token: this.connection.wsAccessConfig.token,\r\n        //     },\r\n        //   };\r\n        //   console.log(socketMessage)\r\n        //   this.connection.socket.send(JSON.stringify(socketMessage));\r\n        // }\r\n        // if (conversationMeta && this.connection.socket) {\r\n        //   const socketMessage = {\r\n        //     action: ServerActions.EDIT_MESSAGE,\r\n        //     message: {\r\n        //       ...updatedMessage,\r\n        //       token: this.connection.wsAccessConfig.token,\r\n        //     },\r\n        //   };\r\n        //   this.connection.socket.send(JSON.stringify(socketMessage));\r\n        //   var prevMessage = conversationMeta.conversation.messages.find(\r\n        //     (m) => m.messageId === message.messageId\r\n        //   );\r\n        //   if (prevMessage) {\r\n        //     var editedMessage = {\r\n        //       ...prevMessage,\r\n        //       message: message.textMessage,\r\n        //       lastEdited: new Date(),\r\n        //     };\r\n        //     var updatedMessageList = conversationMeta.conversation.messages.map(\r\n        //       (m) => {\r\n        //         if (m.messageId === message.messageId) {\r\n        //           return editedMessage;\r\n        //         }\r\n        //         return m;\r\n        //       }\r\n        //     );\r\n        //     this.connection.conversationListMeta[message.conversationId] = {\r\n        //       conversation: {\r\n        //         ...conversationMeta.conversation,\r\n        //         messages: updatedMessageList,\r\n        //       },\r\n        //       lastMessage: { ...editedMessage },\r\n        //       unread: conversationMeta.unread,\r\n        //     };\r\n        //     this.connection.emit(Events.CONVERSATION_LIST_META_CHANGED, {\r\n        //       conversationListMeta: this.connection.conversationListMeta,\r\n        //     });\r\n        //     // update message copy on broadcast chat screen\r\n        //     this.connection.emit(Events.BROADCAST_LIST_META_CHANGED, {\r\n        //       broadcastListMeta: this.connection.broadcastListMeta,\r\n        //     });\r\n        //   }\r\n        // }\r\n      }\r\n    } catch (error) {\r\n      // maybe an error listener instead\r\n      console.error(error);\r\n    }\r\n  }\r\n\r\n  _updateMessageReactions(\r\n    conversationId: string,\r\n    messageId: string,\r\n    reactions: Reaction[],\r\n    config?: { ws: boolean; to: string }\r\n  ) {\r\n    try {\r\n      this.connection.emit(Events.EDITED_MESSAGE, {\r\n        message: { messageId, reactions },\r\n      });\r\n      // should also send to the lastMessage in conversations meta.\r\n      if (config?.ws) {\r\n        const reactionPayload = {\r\n          action: ServerActions.SEND_MESSAGE_REACTION,\r\n          message: {\r\n            conversationId,\r\n            messageId: messageId,\r\n            from: this.connection.userMeta.uid,\r\n            to: config.to,\r\n            reactions,\r\n            token: this.connection.wsAccessConfig.token,\r\n            user: this.connection.userMeta\r\n          },\r\n        };\r\n        this.connection.socket.send(JSON.stringify(reactionPayload));\r\n      }\r\n\r\n      var conversationMeta =\r\n        this.connection.conversationListMeta[conversationId];\r\n      var prevLastMessage = conversationMeta?.lastMessage;\r\n\r\n      if (prevLastMessage && prevLastMessage.messageId === messageId) {\r\n        var updatedMessage = {\r\n          ...prevLastMessage,\r\n          reactions,\r\n        };\r\n        var updatedMessages = this.rotateAndInsertMessageList(\r\n          conversationMeta.conversation.messages,\r\n          updatedMessage\r\n        );\r\n\r\n        var updatedConversationListMeta = {\r\n          conversation: {\r\n            ...conversationMeta.conversation,\r\n            messages: updatedMessages,\r\n          },\r\n          unread: conversationMeta.unread,\r\n          lastMessage: {\r\n            ...updatedMessage,\r\n          },\r\n        };\r\n        this.connection.conversationListMeta[conversationId] =\r\n          updatedConversationListMeta;\r\n        this.connection.emit(Events.CONVERSATION_LIST_META_CHANGED, {\r\n          conversationListMeta: this.connection.conversationListMeta,\r\n        });\r\n      }\r\n    } catch (error) {\r\n      if (error instanceof Error) {\r\n      }\r\n    }\r\n  }\r\n\r\n  private storeEditedMessage(data: EditedMessage) {\r\n    const conversation = this.connection.conversationMap[data.conversationId];\r\n    // const conversation = this.connection.conversationMap[data.conversationId];\r\n    if (conversation) {\r\n      var message = conversation.messages.find(\r\n        (message) => message.messageId === data.messageId\r\n      );\r\n      if (message) {\r\n        const updatedMessage = {\r\n          ...message,\r\n          message: data.textMessage,\r\n          lastEdited: new Date(),\r\n        };\r\n        this.connection.emit(Events.EDITED_MESSAGE, {\r\n          message: updatedMessage,\r\n        });\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   *\r\n   * @param conversationId\r\n   * @summary Updates the list of conversations with typing indicator flags\r\n   */\r\n  private showTypingIndicator = (\r\n    conversationId: string,\r\n    action: \"START\" | \"STOP\"\r\n  ) => {\r\n    if (action === \"START\") {\r\n      this.connection.emit(Events.HAS_STARTED_TYPING, {\r\n        conversationId,\r\n      });\r\n    } else {\r\n      this._clearActiveTypingIndicator(conversationId);\r\n      this.idleTimers[conversationId] = setTimeout(() => {\r\n        this.connection.emit(Events.HAS_STOPPED_TYPING, {\r\n          conversationId,\r\n        });\r\n      }, 4000);\r\n    }\r\n  };\r\n  // sent to message recipient\r\n  private _sendTypingNotification(uid: string) {\r\n    if (this.connection.socket) {\r\n      this.connection.socket.send(\r\n        JSON.stringify({\r\n          action: ServerActions.USER_TYPING,\r\n          message: {\r\n            uid,\r\n            conversationId: this.connection.activeConversationId,\r\n            action: \"START\",\r\n            conversationType: this.getConversationType(\r\n              this.connection.activeConversationId\r\n            ),\r\n            user: this.connection.userMeta,\r\n            token: this.connection.wsAccessConfig.token,\r\n          },\r\n        })\r\n      );\r\n    }\r\n  }\r\n\r\n  private _sendStoppedTypingNotification(uid: string) {\r\n    if (this.connection.socket) {\r\n      this.connection.socket.send(\r\n        JSON.stringify({\r\n          action: ServerActions.USER_TYPING,\r\n          message: {\r\n            uid,\r\n            conversationId: this.connection.activeConversationId,\r\n            action: \"STOP\",\r\n            conversationType: this.getConversationType(\r\n              this.connection.activeConversationId\r\n            ),\r\n            user: this.connection.userMeta,\r\n            token: this.connection.wsAccessConfig.token,\r\n          },\r\n        })\r\n      );\r\n    }\r\n  }\r\n\r\n  private addMessageToConversation(newMessage: Message, screen: string) {\r\n    try {\r\n      const conversation =\r\n        this.connection.conversationMap[newMessage.conversationId];\r\n      if (conversation) {\r\n        const updatedMessages = [\r\n          ...conversation.messages,\r\n          {\r\n            ...newMessage,\r\n            messageState:\r\n              screen === Screens.CHAT ? MessageStates.READ : MessageStates.SENT,\r\n          },\r\n        ];\r\n\r\n        this.connection.conversationMap[newMessage.conversationId] = {\r\n          ...conversation,\r\n          messages: updatedMessages,\r\n        };\r\n        this.connection.emit(Events.NEW_MESSAGE, {\r\n          message: {\r\n            ...newMessage,\r\n            messageState:\r\n              screen === Screens.CHAT ? MessageStates.READ : MessageStates.SENT,\r\n          },\r\n        });\r\n\r\n        const unread = [\r\n          ...this.connection.conversationListMeta[newMessage.conversationId]\r\n            .unread,\r\n        ];\r\n\r\n        if (\r\n          newMessage.conversationId !== this.connection.activeConversationId\r\n        ) {\r\n          unread.push(newMessage.messageId);\r\n        }\r\n\r\n        const updatedConversationListMeta = {\r\n          conversation: {\r\n            ...this.connection.conversationListMeta[newMessage.conversationId]\r\n              .conversation,\r\n            messages: updatedMessages,\r\n          },\r\n          lastMessage: {\r\n            ...newMessage,\r\n          },\r\n          unread: unread,\r\n        };\r\n        this.connection.conversationListMeta[newMessage.conversationId] =\r\n          updatedConversationListMeta;\r\n        this.connection.emit(Events.CONVERSATION_LIST_META_CHANGED, {\r\n          conversationListMeta: this.connection.conversationListMeta,\r\n        });\r\n      }\r\n    } catch (error) {\r\n      console.error(error);\r\n    }\r\n  }\r\n\r\n  private sendReadNotification(data: ReadMessages) {\r\n    if (this.connection.socket) {\r\n      this.connection.socket.send(\r\n        JSON.stringify({\r\n          action: ServerActions.READ_MESSAGES,\r\n          message: { \r\n            ...data,\r\n            user: this.connection.userMeta,\r\n            token: this.connection.wsAccessConfig.token },\r\n        })\r\n      );\r\n    }\r\n  }\r\n\r\n  private _clearActiveTypingIndicator(conversationId: string, emit?: boolean) {\r\n    clearTimeout(this.idleTimers[conversationId]);\r\n    delete this.idleTimers[conversationId];\r\n    if (emit === true) {\r\n      this.connection.emit(Events.HAS_STOPPED_TYPING, {\r\n        conversationId,\r\n      });\r\n    }\r\n  }\r\n\r\n  private _updateConversationListMetaMessages() {}\r\n\r\n  readMessages(conversationId: string, data: ReadMessages) {\r\n    if (this.connection.socket) {\r\n      const socketMessage = {\r\n        action: ServerActions.READ_MESSAGES,\r\n        message: {\r\n          ...data,\r\n          user: this.connection.userMeta,\r\n          token: this.connection.wsAccessConfig.token,\r\n        },\r\n      };\r\n  \r\n      this.connection.socket.send(JSON.stringify(socketMessage));\r\n  \r\n      // Create an updated conversation list meta immutably\r\n      const conversationMeta = this.connection.conversationListMeta[conversationId];\r\n      if (conversationMeta) {\r\n        const updatedConversationListMeta = {\r\n          ...this.connection.conversationListMeta,\r\n          [conversationId]: {\r\n            ...conversationMeta,\r\n            unread: [],  // Clears unread without direct mutation\r\n          },\r\n        };\r\n  \r\n        this.connection.conversationListMeta = updatedConversationListMeta;\r\n        \r\n        this.connection.emit(Events.CONVERSATION_LIST_META_CHANGED, {\r\n          conversationListMeta: updatedConversationListMeta,\r\n        });\r\n      }\r\n    }\r\n  }\r\n  \r\n\r\n  //this is to clear notifications for user who hasn't opened chat\r\n  clearUserUnreadNotifications(conversationId: string, ids: string[]) {\r\n    var i = 0;\r\n    var len = ids.length;\r\n\r\n    while (i < len) {\r\n      this.connection.emit(Events.EDITED_MESSAGE, {\r\n        message: { messageId: ids[i], messageState: MessageStates.READ },\r\n      });\r\n      i++;\r\n    }\r\n  }\r\n\r\n  private wsOnError(error: CloseEvent) {\r\n    this.connection.emit(Events.CONNECTION_CHANGED, {\r\n      isConnected: false,\r\n      connecting: false,\r\n      fetchingConversations: false,\r\n    });\r\n  }\r\n\r\n  private deleteMessageFromConversationMeta(\r\n    conversationId: string,\r\n    messageId: string\r\n  ) {\r\n    try {\r\n      const conversationMeta =\r\n        this.connection.conversationListMeta[conversationId];\r\n\r\n      // check if the message being deleted is the last message\r\n      var isLastMessage = messageId === conversationMeta.lastMessage?.messageId;\r\n\r\n      if (conversationMeta) {\r\n        const filteredMessages = conversationMeta.conversation.messages.filter(\r\n          (m) => m.messageId !== messageId\r\n        );\r\n\r\n        var newLastMessage = filteredMessages[filteredMessages.length - 1];\r\n\r\n        var updatedConversationListMeta = {\r\n          ...conversationMeta,\r\n          conversation: {\r\n            ...conversationMeta.conversation,\r\n            messages: filteredMessages,\r\n          },\r\n        };\r\n\r\n        if (isLastMessage) {\r\n          updatedConversationListMeta.lastMessage = newLastMessage\r\n            ? newLastMessage\r\n            : null;\r\n        }\r\n\r\n        this.connection.conversationListMeta[conversationId] =\r\n          updatedConversationListMeta;\r\n\r\n        this.connection.emit(Events.CONVERSATION_LIST_META_CHANGED, {\r\n          conversationListMeta: this.connection.conversationListMeta,\r\n        });\r\n      } else {\r\n        throw new Error(`Conversation with ID ${conversationId} not found.`);\r\n      }\r\n    } catch (error) {\r\n      if (error instanceof Error) {\r\n        console.error(error.message);\r\n      }\r\n    }\r\n  }\r\n\r\n  reactToMessage({\r\n    conversationId,\r\n    messageId,\r\n    reactions,\r\n    to,\r\n  }: {\r\n    conversationId: string;\r\n    messageId: string;\r\n    reactions: Reaction[];\r\n    to: string;\r\n  }) {\r\n    if (this.connection) {\r\n      this._updateMessageReactions(conversationId, messageId, reactions, {\r\n        ws: true,\r\n        to,\r\n      });\r\n    }\r\n  }\r\n\r\n  sendMessage(newMessage: Prettify<SendMessageGenerics<Message>>) {\r\n    if (this.connection) {\r\n      const messageId = generateId();\r\n      var timeStamps = generateFillerTimestamps();\r\n      var messageOwner = {\r\n        ...this.connection.userMeta,\r\n        ...timeStamps,\r\n      };\r\n      const messageStruct: Message = {\r\n        ...newMessage,\r\n        quotedMessageId: newMessage?.quotedMessage?.messageId,\r\n        from: messageOwner.uid,\r\n        lastEdited: null,\r\n        messageState: MessageStates.LOADING,\r\n        messageOwner,\r\n        messageId,\r\n        ...timeStamps,\r\n      };\r\n      this._createMessage(messageStruct);\r\n    }\r\n  }\r\n\r\n  updateBroadcastList(payload: { broadcastListId: string, participants: string[], name: string }) {\r\n    try {\r\n      if (\r\n        this.connection.socket &&\r\n        this.connection.socket?.readyState === WebSocket.OPEN\r\n      ) {\r\n        const socketMessage = {\r\n          action: ServerActions.DELETE_BROADCAST_LIST,\r\n          message: {\r\n            broadcastListId: payload.broadcastListId,\r\n            participants: payload.participants,\r\n            name: payload.name,\r\n            user: this.connection.userMeta,\r\n            token: this.connection.wsAccessConfig.token,\r\n          },\r\n        };\r\n        this.connection.socket.send(JSON.stringify(socketMessage));\r\n      }else{\r\n        console.error(\"Failed to send broadcast\");\r\n      }\r\n    } catch (error) {\r\n      if(error instanceof Error){\r\n        console.error(error.message)\r\n      }\r\n    }\r\n  }\r\n\r\n  deleteBroadcastList(payload: { broadcastListId: string, participants: string[], name: string }) {\r\n    try {\r\n      if (\r\n        this.connection.socket &&\r\n        this.connection.socket?.readyState === WebSocket.OPEN\r\n      ) {\r\n        const socketMessage = {\r\n          action: ServerActions.UPDATE_BROADCAST_LIST,\r\n          message: {\r\n            broadcastListId: payload.broadcastListId,\r\n            participants: payload.participants,\r\n            name: payload.name,\r\n            user: this.connection.userMeta,\r\n            token: this.connection.wsAccessConfig.token,\r\n          },\r\n        };\r\n        this.connection.socket.send(JSON.stringify(socketMessage));\r\n        if(this.connection.broadcastListMeta[payload.broadcastListId]){{\r\n          delete this.connection.broadcastListMeta[payload.broadcastListId]\r\n          this.connection.emit(Events.BROADCAST_LIST_META_CHANGED, {\r\n            broadcastListMeta: this.connection.broadcastListMeta,\r\n          });\r\n        }}\r\n      }else{\r\n        console.error(\"Failed to send broadcast\");\r\n      }\r\n    } catch (error) {\r\n      if(error instanceof Error){\r\n        console.error(error.message)\r\n      }\r\n    }\r\n  }\r\n\r\n  broadcastMessage(\r\n    { broadcastListId, participantsIds, newMessage }:  { broadcastListId: string, participantsIds: string[], newMessage: Prettify<SendMessageGenerics<Message>> }) {\r\n    try {\r\n      if (\r\n        this.connection.socket &&\r\n        this.connection.socket?.readyState === WebSocket.OPEN\r\n      ) {\r\n        const messageId = generateId();\r\n        var timeStamps = generateFillerTimestamps();\r\n        var messageOwner = {\r\n          ...this.connection.userMeta,\r\n          ...timeStamps,\r\n        };\r\n        const messageStruct: Message = {\r\n          ...newMessage,\r\n          quotedMessageId: newMessage?.quotedMessage?.messageId,\r\n          from: messageOwner.uid,\r\n          lastEdited: null,\r\n          messageState: MessageStates.SENT,\r\n          messageOwner,\r\n          messageId,\r\n          isBroadcast: true,\r\n          broadcastListId,\r\n          ...timeStamps,\r\n        };\r\n\r\n        const socketMessage = {\r\n          action: ServerActions.BROADCAST_MESSAGE,\r\n          message: {\r\n            broadcastListId,\r\n            messageId,\r\n            from: messageOwner.uid,\r\n            to: participantsIds,\r\n            shouldEdit: false,\r\n            conversationType: \"broadcast-chat\",\r\n            message: messageStruct,\r\n            user: this.connection.userMeta,\r\n            token: this.connection.wsAccessConfig.token,\r\n          },\r\n        };\r\n\r\n        var broadcastItem = this.connection.broadcastListMeta[broadcastListId];\r\n        var messages = [...broadcastItem.conversation.messages];\r\n\r\n        messages.push(messageStruct);\r\n\r\n        var updatedBroadCastItem = { \r\n          conversation: { ...broadcastItem.conversation, messages },\r\n          lastMessage: null,\r\n          unread: []\r\n         };\r\n        this.connection.broadcastListMeta[broadcastListId] = updatedBroadCastItem;\r\n\r\n        this.connection.socket.send(JSON.stringify(socketMessage));\r\n\r\n        participantsIds.map(p => {\r\n          // send out new message events for any active listeners\r\n          const conversationId = generateConversationId(p, messageOwner.uid, this.connection.projectConfig.projectId);\r\n          this.connection.emit(Events.NEW_MESSAGE, {\r\n            message: {\r\n              ...messageStruct,\r\n              conversationId,\r\n              reactions: [],\r\n            },\r\n          });\r\n          var prevConversation = this.connection.conversationListMeta[conversationId]\r\n          // if a conversation exists, update all user conversations in conversationListMeta\r\n          if(prevConversation){\r\n            this.connection.conversationListMeta[conversationId] = {\r\n              conversation: {\r\n                ...prevConversation.conversation,\r\n                messages: [ ...prevConversation.conversation.messages, {\r\n                  ...messageStruct,\r\n                  conversationId,\r\n                  reactions: [],\r\n                } ],\r\n              },\r\n              lastMessage: {\r\n                ...messageStruct,\r\n                conversationId,\r\n                reactions: [],\r\n              },\r\n              unread: prevConversation.unread,\r\n            };\r\n          }\r\n        });\r\n        // send the updated conversationListMeta to active listeners\r\n        this.connection.emit(Events.CONVERSATION_LIST_META_CHANGED, {\r\n          conversationListMeta: this.connection.conversationListMeta,\r\n        });\r\n\r\n        // send a new message event for the current broadcast chat\r\n        this.connection.emit(Events.NEW_MESSAGE, {\r\n          message: {\r\n            ...messageStruct,\r\n            conversationId: broadcastListId,\r\n            reactions: [],\r\n          },\r\n        });\r\n\r\n        this.connection.emit(Events.BROADCAST_LIST_META_CHANGED, {\r\n          broadcastListMeta: this.connection.broadcastListMeta,\r\n        });\r\n      } else {\r\n        console.error(\"Failed to send broadcast\");\r\n      }\r\n    } catch (error) {\r\n      if (error instanceof Error) {\r\n        console.error(error.message);\r\n      }\r\n    }\r\n  }\r\n\r\n  editMessage(message: Omit<EditedMessage, \"from\">) {\r\n    if (this.connection) {\r\n      this._editMessage({\r\n        ...message,\r\n        from: this.connection.userMeta.uid,\r\n      });\r\n    }\r\n  }\r\n\r\n  sendTypingNotification(uid: string) {\r\n    if (this.connection) {\r\n      this._sendTypingNotification(uid);\r\n    }\r\n  }\r\n\r\n  sendStoppedTypingNotification(uid: string) {\r\n    if (this.connection) {\r\n      this._sendStoppedTypingNotification(uid);\r\n    }\r\n  }\r\n\r\n  deleteMessage(messageId: string, to: string, conversationId: string) {\r\n    if (this.connection) {\r\n      this.connection.socket.send(\r\n        JSON.stringify({\r\n          action: ServerActions.DELETE_MESSAGE,\r\n          message: {\r\n            messageId,\r\n            to,\r\n            conversationId,\r\n            conversationType: this.getConversationType(),\r\n            user: this.connection.userMeta,\r\n            token: this.connection.wsAccessConfig.token,\r\n          },\r\n        })\r\n      );\r\n      this.connection.emit(Events.DELETED_MESSAGE, {\r\n        message: {\r\n          conversationId,\r\n          messageId,\r\n        },\r\n      });\r\n      this.deleteMessageFromConversationMeta(conversationId, messageId);\r\n    }\r\n  }\r\n\r\n  async getMessages(page?: number) {\r\n    if (this.connection) {\r\n      try {\r\n        const response = await GET_MESSAGES<{ messages: Message[] }>(\r\n          this.connection.wsAccessConfig.token,\r\n          this.connection.activeConversationId,\r\n          page\r\n        );\r\n        if (response.success) {\r\n          const sortedMessages = [...response.data.messages].sort((a, b) => {\r\n            const dateA = moment(a.createdAt).valueOf();\r\n            const dateB = moment(b.createdAt).valueOf();\r\n            return dateA - dateB;\r\n          });\r\n          return sortedMessages;\r\n        } else {\r\n          return [];\r\n        }\r\n      } catch (err) {\r\n        console.error(err);\r\n        return [];\r\n      }\r\n    } else {\r\n      return [];\r\n    }\r\n  }\r\n\r\n  async getBroadcastListMessages(page?: number) {\r\n    if (this.connection) {\r\n      try {\r\n        const response = await GET_BROADCAST_LIST_MESSAGES<{\r\n          messages: Message[];\r\n        }>(\r\n          this.connection.wsAccessConfig.token,\r\n          this.connection.activeConversationId,\r\n          page\r\n        );\r\n        if (response.success) {\r\n          const sortedMessages = [...response.data.messages].sort((a, b) => {\r\n            const dateA = moment(a.createdAt).valueOf();\r\n            const dateB = moment(b.createdAt).valueOf();\r\n            return dateA - dateB;\r\n          });\r\n          return sortedMessages;\r\n        } else {\r\n          return [];\r\n        }\r\n      } catch (err) {\r\n        console.error(err);\r\n        return [];\r\n      }\r\n    } else {\r\n      return [];\r\n    }\r\n  }\r\n\r\n  async getConversation(conversationId: string) {\r\n    if (this.connection) {\r\n      try {\r\n        const response = await GET_CONVERSATION<{ conversation: Conversation }>(\r\n          this.connection.wsAccessConfig.token,\r\n          conversationId\r\n        );\r\n        if (response.success) {\r\n          return response.data.conversation;\r\n        } else {\r\n          return null;\r\n        }\r\n      } catch (err) {\r\n        return null;\r\n      }\r\n    } else {\r\n      return null;\r\n    }\r\n  }\r\n\r\n  async getEmojiList() {\r\n    if (this.connection) {\r\n      try {\r\n        const response = await GET_EMOJIS<{ gifs: Emoticon[] }>(\r\n          this.connection.wsAccessConfig.token\r\n        );\r\n        return response.data.gifs;\r\n      } catch (err) {\r\n        return [];\r\n      }\r\n    } else {\r\n      return [];\r\n    }\r\n  }\r\n\r\n  async uploadAttachment({\r\n    base64,\r\n    fileKey,\r\n  }: {\r\n    base64: string;\r\n    fileKey: string;\r\n  }) {\r\n    if (this.connection) {\r\n      try {\r\n        const res = await UPLOAD_MEDIA<{ url: string }>(\r\n          this.connection.wsAccessConfig?.token,\r\n          {\r\n            base64,\r\n            conversationId: this.connection.activeConversationId,\r\n            key: fileKey,\r\n          }\r\n        );\r\n        return res;\r\n      } catch (error) {\r\n        if (error instanceof Error) {\r\n          console.error(error.message);\r\n        }\r\n      }\r\n    } else {\r\n      throw new Error(\"No connection established\");\r\n    }\r\n  }\r\n\r\n  private isReadableStream(uri: any): uri is Readable {\r\n    return uri && typeof uri.pipe === \"function\";\r\n  }\r\n\r\n  async uploadFile(\r\n    uri: string | NodeJS.ReadableStream | Buffer | File,\r\n    meta: {\r\n      filename: string;\r\n      mimeType: string;\r\n      ext: string\r\n    }\r\n  ) {\r\n    try {\r\n      // Get the presigned URL for upload\r\n      const res = await GET_PRESIGNED_URL<{\r\n        uploadUrl: string;\r\n        s3Link: string;\r\n      }>(this.connection.wsAccessConfig?.token, {\r\n        base64: \"\",\r\n        conversationId: this.connection.activeConversationId,\r\n        key: generateId(),\r\n        mediaType: meta.mimeType,\r\n        uid: this.connection.userMeta.uid,\r\n        ext: meta.ext\r\n      });\r\n\r\n      let body;\r\n\r\n      let fileSize = 0; // Initialize file size\r\n\r\n      if (typeof uri === \"string\") {\r\n        const response = await fetch(uri); // Fetch the file data from URI\r\n        body = await response.blob(); // Convert it to a Blob\r\n        fileSize = body.size;\r\n      }\r\n      // Check if the input is a File object (e.g., browser)\r\n      else if (uri instanceof File) {\r\n        body = uri;\r\n        fileSize = uri.size;\r\n      }\r\n      // Check if the input is a Buffer (Node.js)\r\n      else if (Buffer.isBuffer(uri)) {\r\n        body = new Blob([uri], { type: meta.mimeType });\r\n        fileSize = uri.length;\r\n      }\r\n      // Check if the input is a Node.js Readable stream\r\n      else if (this.isReadableStream(uri)) {\r\n        const chunks: any[] = [];\r\n        let totalSize = 0;\r\n        for await (const chunk of uri) {\r\n          chunks.push(chunk);\r\n          totalSize += chunk.length; // Accumulate size\r\n        }\r\n        const buffer = Buffer.concat(chunks);\r\n        body = new Blob([buffer], { type: meta.mimeType });\r\n        fileSize = totalSize;\r\n      }\r\n\r\n      await fetch(res.data.uploadUrl, {\r\n        method: \"PUT\",\r\n        body: body,\r\n        headers: {\r\n          \"Content-Type\": meta.mimeType,\r\n        },\r\n      });\r\n\r\n      return {\r\n        link: res.data.s3Link,\r\n        success: res.success,\r\n        fileSize,\r\n      };\r\n    } catch (error) {\r\n      console.log(error);\r\n      console.error(\"Error uploading file: \", error);\r\n      return {\r\n        link: \"\",\r\n        success: false,\r\n        fileSize: \"\",\r\n      };\r\n    }\r\n  }\r\n\r\n  async uploadAttachmentV2({\r\n    base64,\r\n    fileKey,\r\n    mediaType,\r\n    mimeType,\r\n  }: {\r\n    base64: string;\r\n    fileKey: string;\r\n    mediaType: MediaType;\r\n    mimeType: string;\r\n  }) {\r\n    if (this.connection) {\r\n      try {\r\n        const res = await GET_PRESIGNED_URL<{\r\n          uploadUrl: string;\r\n          s3Link: string;\r\n        }>(this.connection.wsAccessConfig?.token, {\r\n          base64,\r\n          conversationId: this.connection.activeConversationId,\r\n          key: generateId(),\r\n          mediaType,\r\n          uid: this.connection.userMeta.uid,\r\n          ext: \"\"\r\n        });\r\n        const data = await fetch(res.data.uploadUrl, {\r\n          method: \"PUT\",\r\n          body: {\r\n            base64,\r\n            fileKey,\r\n            mediaType,\r\n          } as any,\r\n          headers: {\r\n            \"Content-Type\": mimeType,\r\n          },\r\n        });\r\n        return res;\r\n      } catch (error) {\r\n        if (error instanceof Error) {\r\n          console.error(error.message);\r\n        }\r\n      }\r\n    } else {\r\n      throw new Error(\"No connection established\");\r\n    }\r\n  }\r\n\r\n  async setActiveConversation() {\r\n    if (this.connection) {\r\n      this.connection.screen = Screens.CHAT;\r\n      this.screen = Screens.CHAT;\r\n    } else {\r\n      throw new Error(\"No connection established\");\r\n    }\r\n  }\r\n\r\n  async unSetActiveConversation() {\r\n    if (this.connection) {\r\n      this.connection.activeConversationId = \"\";\r\n      this.connection.screen = Screens.CONVERSATIONS;\r\n      this.screen = Screens.CONVERSATIONS;\r\n    } else {\r\n      throw new Error(\"No connection established\");\r\n    }\r\n  }\r\n\r\n  messageEventHandler(event: MessageEvent) {\r\n    try {\r\n      if (!event) return null;\r\n      var wsData = JSON.parse(event.data);\r\n      const action: ClientActions | ServerActions = wsData.action;\r\n      if (\r\n        this.screen === Screens.CHAT &&\r\n        this.connection.activeConversationId === wsData?.message?.conversationId\r\n        // this.connection.activeConversationId === wsData?.message?.conversationId\r\n      ) {\r\n        // read messages if user is still on the screen\r\n        if (action === ClientActions.INCOMING_MESSAGE) {\r\n          const {\r\n            message: incomingMessagePayload,\r\n          }: WsPayLoad<ServerActions, Message> = JSON.parse(event.data);\r\n\r\n          // clear typing indicator timeout\r\n          this._clearActiveTypingIndicator(\r\n            this.connection.activeConversationId,\r\n            true\r\n          );\r\n\r\n          this.sendReadNotification({\r\n            uid: incomingMessagePayload.from,\r\n            messageIds: [incomingMessagePayload.messageId],\r\n          });\r\n        }\r\n\r\n        // to read the message as they come in\r\n        if (action === ClientActions.MESSAGES_READ) {\r\n          const {\r\n            message: readMessagesPayload,\r\n          }: WsPayLoad<\r\n            ClientActions,\r\n            ReadMessages & { conversationId: string }\r\n          > = wsData;\r\n          // const existingConversationForRead = this.connection.conversationMap[readMessagesPayload.conversationId]\r\n          if (\r\n            // existingConversationForRead &&\r\n            this.screen === Screens.CHAT &&\r\n            this.connection.activeConversationId ===\r\n              readMessagesPayload.conversationId\r\n          ) {\r\n            setTimeout(() => {\r\n              this.clearUserUnreadNotifications(\r\n                readMessagesPayload.conversationId,\r\n                readMessagesPayload.messageIds\r\n              );\r\n            }, CLEAR_UNREAD_TIMEOUT);\r\n          }\r\n        }\r\n      }\r\n      switch (action) {\r\n        case ClientActions.MESSAGES_READ:\r\n          const {\r\n            message: readMessagesPayload,\r\n          }: WsPayLoad<\r\n            ClientActions,\r\n            ReadMessages & { conversationId: string }\r\n          > = wsData;\r\n          const existingConversationForRead =\r\n            this.connection.conversationMap[readMessagesPayload.conversationId];\r\n          if (existingConversationForRead && this.screen === Screens.CHAT) {\r\n            setTimeout(() => {\r\n              // if user reads message immediately, then they are online\r\n              // this.updateActiveConversations(readMessagesPayload.conversationId);\r\n              this.clearUserUnreadNotifications(\r\n                readMessagesPayload.conversationId,\r\n                readMessagesPayload.messageIds\r\n              );\r\n            }, CLEAR_UNREAD_TIMEOUT);\r\n          }\r\n          break;\r\n        case ClientActions.INCOMING_MESSAGE:\r\n          const {\r\n            message: incomingMessagePayload,\r\n          }: WsPayLoad<\r\n            ClientActions,\r\n            {\r\n              message: Message;\r\n              senderMeta: UserMeta;\r\n              conversationType: ConversationType;\r\n            }\r\n          > = wsData;\r\n          var incomingMessage = incomingMessagePayload.message;\r\n          const existingConversation =\r\n            this.connection.conversationMap[incomingMessage.conversationId];\r\n          this._clearActiveTypingIndicator(\r\n            incomingMessage.conversationId,\r\n            true\r\n          );\r\n\r\n          if (existingConversation) {\r\n            this.addMessageToConversation(incomingMessage, this.screen);\r\n          } else {\r\n            const newConversationId =\r\n              incomingMessagePayload.conversationType === \"private-chat\"\r\n                ? generateConversationId(\r\n                    incomingMessage.from,\r\n                    incomingMessage.to,\r\n                    this.connection.projectConfig.projectId\r\n                  )\r\n                : incomingMessagePayload.message.conversationId;\r\n            const newMessage = {\r\n              ...incomingMessage,\r\n              messageId: generateId(),\r\n              messageState: MessageStates.SENT,\r\n              createdAt: new Date(),\r\n            };\r\n            var newConversation = {\r\n              participants: [newMessage.from, newMessage.to],\r\n              conversationId: generateConversationId(\r\n                newMessage.from,\r\n                newMessage.to,\r\n                this.connection.projectConfig.projectId\r\n              ),\r\n              messages: [newMessage],\r\n              admins: [newMessage.from],\r\n              meta: null,\r\n              groupMeta: null,\r\n              conversationType: incomingMessagePayload.conversationType,\r\n              participantList: [\r\n                {\r\n                  id: generateId(),\r\n                  uid: newMessage.from,\r\n                  connectionId: \"--\",\r\n                  participantId: newMessage.from,\r\n                  projectId: \"--\",\r\n                  participantDetails: {\r\n                    // projectId: \"--\",\r\n                    // uid: this.connection.userMeta.uid,\r\n                    // connectionId: \"--\",\r\n                    // meta: incomingMessagePayload.senderMeta,\r\n                    ...incomingMessagePayload.senderMeta,\r\n                    ...generateFillerTimestamps(),\r\n                  },\r\n                  ...generateFillerTimestamps(),\r\n                },\r\n                {\r\n                  id: generateId(),\r\n                  uid: newMessage.to,\r\n                  connectionId: \"--\",\r\n                  participantId: newMessage.to,\r\n                  projectId: \"--\",\r\n                  participantDetails: {\r\n                    // projectId: \"--\",\r\n                    // uid: this.connection.userMeta.uid,\r\n                    // connectionId: \"--\",\r\n                    // meta: this.connection.userMeta,\r\n                    ...this.connection.userMeta,\r\n                    ...generateFillerTimestamps(),\r\n                  },\r\n                  ...generateFillerTimestamps(),\r\n                },\r\n              ],\r\n              ...generateFillerTimestamps(),\r\n            };\r\n\r\n            const newConversationMeta = {\r\n              conversation: newConversation,\r\n              lastMessage: newMessage,\r\n              unread: [],\r\n            };\r\n            this.connection.conversationListMeta[newConversationId] =\r\n              newConversationMeta;\r\n            this.connection.emit(Events.CONVERSATION_LIST_META_CHANGED, {\r\n              conversationListMeta: this.connection.conversationListMeta,\r\n            });\r\n          }\r\n          break;\r\n        case ClientActions.USER_IS_TYPING:\r\n          const {\r\n            message: userTypingPayload,\r\n          }: WsPayLoad<\r\n            ClientActions,\r\n            { conversationId: string; action: \"START\" | \"STOP\" }\r\n          > = wsData;\r\n\r\n          this.showTypingIndicator(\r\n            userTypingPayload.conversationId,\r\n            userTypingPayload.action\r\n          );\r\n          break;\r\n        case ClientActions.NEW_MESSAGE_REACTION:\r\n          const {\r\n            message: messageReactionPayload,\r\n          }: WsPayLoad<\r\n            ClientActions,\r\n            {\r\n              conversationId: string;\r\n              messageId: string;\r\n              from: string;\r\n              to: string;\r\n              reactions: Reaction[];\r\n            }\r\n          > = wsData;\r\n          this._updateMessageReactions(\r\n            messageReactionPayload.conversationId,\r\n            messageReactionPayload.messageId,\r\n            messageReactionPayload.reactions\r\n          );\r\n          break;\r\n        case ClientActions.MESSAGE_ERROR:\r\n          const {\r\n            message: errorPayload,\r\n          }: WsPayLoad<ClientActions, { error: string }> = wsData;\r\n          console.error(\r\n            \"Failed to send message, please try again\",\r\n            errorPayload\r\n          );\r\n          break;\r\n        case ClientActions.EDITED_MESSAGE:\r\n          const {\r\n            message: editedMessage,\r\n          }: WsPayLoad<ClientActions, EditedMessage> = wsData;\r\n          this._clearActiveTypingIndicator(editedMessage.conversationId, true);\r\n          this.storeEditedMessage(editedMessage);\r\n          break;\r\n        case ClientActions.MESSAGE_DELETED:\r\n          const {\r\n            message: deletedMessage,\r\n          }: WsPayLoad<ClientActions, DeletedMessage> = wsData;\r\n          this.connection.emit(Events.DELETED_MESSAGE, {\r\n            message: deletedMessage,\r\n          });\r\n          this.deleteMessageFromConversationMeta(\r\n            deletedMessage.conversationId,\r\n            deletedMessage.messageId\r\n          );\r\n          break;\r\n        case ClientActions.ACK_HEALTH_CHECK:\r\n          console.info(\"HEALTH_CHECK: ok!\");\r\n          break;\r\n        default:\r\n          console.log(\"Unknown action recieved\");\r\n      }\r\n\r\n      this.connection.socket.onerror = (error: CloseEvent) => {\r\n        this.wsOnError(error);\r\n      };\r\n      // }\r\n    } catch (error) {\r\n      console.error(error);\r\n    }\r\n  }\r\n}\r\n","import ChatClient, { NotificationConfig } from \"./ChatClient\";\r\nimport MessageClient from \"./MessageClient\";\r\nimport {\r\n  CREATE_SESSION,\r\n  GET_BROADCASTLISTS,\r\n  GET_CONVERSATIONS,\r\n  GET_EMOJIS,\r\n  GET_MESSAGES,\r\n  UPLOAD_MEDIA,\r\n} from \"./fetch\";\r\nimport {\r\n  BroadcastListMeta,\r\n  Config,\r\n  Conversation,\r\n  ConversationListMeta,\r\n  ConversationMap,\r\n  EditedMessage,\r\n  Message,\r\n  MessageStates,\r\n  Reaction,\r\n  Screens,\r\n  ServerActions,\r\n  UserMeta,\r\n  WsAccessConfig,\r\n} from \"./types\";\r\nimport WebSocket from \"isomorphic-ws\";\r\nimport EventEmitter from \"events\";\r\nimport { Events } from \"./events\";\r\nimport { Emoticon } from \"./emoticon.type\";\r\nimport moment from \"moment\";\r\n\r\nlet defaultUser = {\r\n  id: \"\",\r\n  uid: \"\",\r\n  username: \"\",\r\n  firstname: \"\",\r\n  lastname: \"\",\r\n  profileUrl: \"\",\r\n  color: \"\",\r\n  custom: {},\r\n};\r\n\r\nlet defaultNotificationConfig = { type: null, token: null }\r\n\r\nexport const connectionStates = {\r\n  NO_CONNECTION: {\r\n    connecting: false,\r\n    isConnected: false,\r\n    fetchingConversations: false,\r\n  },\r\n  GETTING_CONVERSATIONS: {\r\n    connecting: true,\r\n    isConnected: false,\r\n    fetchingConversations: true,\r\n  },\r\n  SOCKET_CONNECTING: {\r\n    connecting: true,\r\n    isConnected: false,\r\n    fetchingConversations: false,\r\n  },\r\n  SOCKET_CONNECTED: {\r\n    connecting: false,\r\n    isConnected: true,\r\n    fetchingConversations: false,\r\n  },\r\n} as const;\r\n\r\nexport type ConnectionState = typeof connectionStates[keyof typeof connectionStates];\r\n\r\nexport default class Connection extends EventEmitter {\r\n  private static connection: Connection;\r\n  connecting: boolean;\r\n  socket: WebSocket | null;\r\n  conversations: Array<Conversation>;\r\n  conversationMap: ConversationMap;\r\n  // wsConnected: boolean;\r\n  wsAccessConfig: WsAccessConfig;\r\n  // fetchingConversations: boolean;\r\n  retry_delay_ms: number;\r\n  max_retry_count: number;\r\n  health_check_interval: number;\r\n  retry_count: number;\r\n  userMeta: UserMeta;\r\n  projectConfig: Config;\r\n  activeConversationId: string;\r\n  screen: Screens;\r\n  broadcastListMeta: ConversationListMeta;\r\n  conversationListMeta: ConversationListMeta; // lastMessage field should be changed to use the last message in the conversation\r\n  private healthCheckRef: NodeJS.Timeout | undefined;\r\n  private retryRef: NodeJS.Timeout | undefined;\r\n  shouldReconnect: boolean;\r\n  connectionState: ConnectionState;\r\n  notificationConfig: NotificationConfig\r\n\r\n  constructor(client_instance: ChatClient) {\r\n    super();\r\n    this.connecting = false;\r\n    this.socket = null;\r\n    this.conversations = [];\r\n    this.conversationMap = {};\r\n    this.conversationListMeta = {};\r\n    this.broadcastListMeta = {};\r\n    this.wsAccessConfig = { url: \"\", token: \"\" };\r\n    this.retry_delay_ms = 5000;\r\n    this.max_retry_count = 5;\r\n    this.health_check_interval = 30000;\r\n    this.retry_count = 0;\r\n    this.userMeta = defaultUser;\r\n    (this.projectConfig = {\r\n      projectId: client_instance.projectId,\r\n      subId: client_instance.subId,\r\n    }),\r\n      (this.activeConversationId = \"\");\r\n    this.screen = Screens.CONVERSATIONS;\r\n    this.healthCheckRef = undefined;\r\n    this.shouldReconnect = true;\r\n    this.connectionState = connectionStates.NO_CONNECTION;\r\n    this.notificationConfig = { type: null, token: null };\r\n  }\r\n\r\n  static getInstance(client_instance: ChatClient) {\r\n    if (Connection.connection) {\r\n      return Connection.connection;\r\n    }\r\n    Connection.connection = new Connection(client_instance);\r\n    return Connection.connection;\r\n  }\r\n\r\n  updateConnectionState(state: ConnectionState) {\r\n    this.connectionState = state\r\n    this.emit(Events.CONNECTION_CHANGED, state);\r\n  }\r\n\r\n  private async _getConversations({ token }: { token: string }) {\r\n    try {\r\n      if (this.userMeta) {\r\n        // this.fetchingConversations = true;\r\n        this.updateConnectionState(connectionStates.GETTING_CONVERSATIONS)\r\n        const response = await GET_CONVERSATIONS<{\r\n          conversations: Conversation[];\r\n        }>(token);\r\n        if (response.success) {\r\n          const conversationListMeta: ConversationListMeta =\r\n            response.data.conversations.reduce((acc, conversation) => {\r\n              var sortedConversation = this.sortConversationMessages([\r\n                conversation,\r\n              ]);\r\n              var messages = sortedConversation[0].messages;\r\n              var lastMessage = messages[messages.length - 1];\r\n\r\n              acc[conversation.conversationId] = {\r\n                conversation: sortedConversation[0],\r\n                lastMessage: lastMessage,\r\n                unread: this._getUreadMessageIds(this.userMeta.uid, messages),\r\n              };\r\n              return acc;\r\n            }, {} as ConversationListMeta);\r\n          var conversationMap = response.data.conversations.reduce(\r\n            (acc, conversation) => {\r\n              acc[conversation.conversationId] = conversation;\r\n              return acc;\r\n            },\r\n            {} as ConversationMap\r\n          );\r\n          this.conversationMap = conversationMap;\r\n\r\n          this.emit(Events.CONVERSATION_LIST_META_CHANGED, {\r\n            conversationListMeta,\r\n          });\r\n          this.conversationListMeta = conversationListMeta;\r\n\r\n          // this.conversations = this.sortConversationMessages(\r\n          //   response.data.conversations\r\n          // );\r\n          this.conversations = response.data.conversations;\r\n        } else {\r\n          console.error(\"An error occurred while fetching conversations\");\r\n        }\r\n      } else {\r\n        throw new Error(\"User not initialized\");\r\n      }\r\n    } catch (err) {\r\n      if (err instanceof Error) {\r\n        console.error(err);\r\n      }\r\n    } finally {\r\n      // this.fetchingConversations = false;\r\n    }\r\n  }\r\n\r\n  \r\n  private async _getBroadcastLists({ token }: { token: string }) {\r\n    try {\r\n      if (this.userMeta) {\r\n        // this.fetchingConversations = true;\r\n        const response = await GET_BROADCASTLISTS<{\r\n          conversations: Conversation[];\r\n        }>(token);\r\n        if (response.success) {\r\n          const broadcastListMeta: ConversationListMeta =\r\n            response.data.conversations.reduce((acc, conversation) => {\r\n              var sortedConversation = this.sortConversationMessages([\r\n                conversation,\r\n              ]);\r\n              var messages = sortedConversation[0].messages;\r\n              var lastMessage = messages[messages.length - 1];\r\n\r\n              acc[conversation.conversationId] = {\r\n                conversation: sortedConversation[0],\r\n                lastMessage: lastMessage,\r\n                unread: []\r\n              };\r\n              return acc;\r\n            }, {} as ConversationListMeta);\r\n          \r\n          this.emit(Events.BROADCAST_LIST_META_CHANGED, {\r\n            broadcastListMeta,\r\n          });\r\n          this.broadcastListMeta = broadcastListMeta;\r\n        } else {\r\n          console.error(\"An error occurred while fetching broadcast lists\");\r\n        }\r\n      } else {\r\n        throw new Error(\"User not initialized\");\r\n      }\r\n    } catch (err) {\r\n      if (err instanceof Error) {\r\n        console.error(err);\r\n      }\r\n    } finally {\r\n      // this.fetchingConversations = false;\r\n    }\r\n  }\r\n\r\n\r\n  async _initiateConnection(\r\n    user: UserMeta,\r\n    config?: {\r\n      notificationConfig?: NotificationConfig;\r\n      connectionConfig?: { reset: boolean };\r\n    }\r\n  ) {\r\n    try {\r\n    \r\n      this.shouldReconnect = true;\r\n      this.userMeta = user;\r\n      if (config?.connectionConfig?.reset) {\r\n        this.retry_count = 0;\r\n      }\r\n      // Ensure we have a valid userMeta.uid\r\n      if (!this.userMeta?.uid) return null;\r\n\r\n      // Clear previous health check interval\r\n      clearTimeout(this.retryRef);\r\n      clearTimeout(this.retryRef);\r\n\r\n      if(config?.notificationConfig){\r\n        this.notificationConfig = config.notificationConfig\r\n      }\r\n      // Create a session to retrieve token and wsURI\r\n      const res = await CREATE_SESSION<{ token: string; wsURI: string }>({\r\n        userId: this.userMeta.uid,\r\n        projectId: this.projectConfig.projectId,\r\n        subId: this.projectConfig.subId,\r\n      });\r\n      // If session creation was successful\r\n      if (res.success) {\r\n        // if(this.retryRef){\r\n        //   clearInterval(this.retryRef)\r\n        // }\r\n        this.wsAccessConfig = {\r\n          url: res.data.wsURI,\r\n          token: res.data.token,\r\n        };\r\n        // Fetch conversations after acquiring the session\r\n        await Promise.all([ await this._getConversations({\r\n          token: res.data.token,\r\n        }), await this._getBroadcastLists({ token: res.data.token })])\r\n       \r\n        this.updateConnectionState(connectionStates.SOCKET_CONNECTING)\r\n        // this.emit(Events.CONNECTION_CHANGED, connectionStates.SOCKET_CONNECTING);\r\n\r\n        // Define the message to send on connection\r\n        const message = JSON.stringify({\r\n          from: this.userMeta.uid,\r\n          to: \"\",\r\n          action: ServerActions.INITIALIZE,\r\n          userMeta: {\r\n            ...this.userMeta,\r\n          },\r\n          newConversation: true,\r\n          recipientMeta: {},\r\n          projectId: this.projectConfig.projectId,\r\n          notification: this.notificationConfig\r\n        });\r\n\r\n        // Check if WebSocket is already open\r\n        if (this.socket && this.socket.readyState === WebSocket.OPEN) {\r\n          this.socket.send(message); // send the message\r\n          // this.wsConnected = true;\r\n\r\n          // Emit successful connection state\r\n          this.updateConnectionState(connectionStates.SOCKET_CONNECTED)\r\n          // this.emit(Events.CONNECTION_CHANGED, connectionStates.SOCKET_CONNECTED);\r\n        } else {\r\n          if (this.socket) {\r\n            this.socket.close();\r\n          }\r\n          // If socket is not open, create a new WebSocket connection\r\n          const ws = new WebSocket(`wss://${this.wsAccessConfig.url}`);\r\n          // Handle WebSocket open event\r\n          ws.onopen = () => {\r\n            console.log(\"socket opened\");\r\n            this.socket = ws; // Set the active socket\r\n\r\n            // Send the initial message\r\n            ws.send(message);\r\n            // this.wsConnected = true;\r\n\r\n            // Setup event handlers and start health checks\r\n            this.setupEventHandlers();\r\n            // this.startHealthCheck();\r\n\r\n            // Emit connection success\r\n            this.connecting = false;\r\n            this.updateConnectionState(connectionStates.SOCKET_CONNECTED)\r\n            // this.emit(Events.CONNECTION_CHANGED, connectionStates.SOCKET_CONNECTED);\r\n\r\n            // Emit updated conversation list\r\n            this.emit(Events.CONVERSATION_LIST_CHANGED, {\r\n              conversations: this.conversations,\r\n            });\r\n            this.retry_count = 0;\r\n          };\r\n        }\r\n      } else {\r\n        // Handle unsuccessful session creation\r\n        // this.wsConnected = false;\r\n        this.updateConnectionState(connectionStates.NO_CONNECTION)\r\n        // this.emit(Events.CONNECTION_CHANGED, connectionStates.NO_CONNECTION);\r\n      }\r\n    } catch (error) {\r\n      // Handle general errors\r\n      console.error(\"Connection error:\", error);\r\n      // this.wsConnected = false;\r\n      this.updateConnectionState(connectionStates.NO_CONNECTION)\r\n      // this.emit(Events.CONNECTION_CHANGED, connectionStates.NO_CONNECTION);\r\n\r\n      // Needs to be handled better\r\n      console.warn(\"Connection error. Attempting to reconnect...\");\r\n      this.retryConnection();\r\n    } finally {\r\n    }\r\n  }\r\n\r\n  private sortMesssages(messages: Array<Message>) {\r\n    var sorted = messages.sort((a, b) => {\r\n      const dateA = new Date(a.createdAt).getTime();\r\n      const dateB = new Date(b.createdAt).getTime();\r\n      return dateB - dateA;\r\n    });\r\n    return sorted;\r\n  }\r\n\r\n  private sortConversationMessages(data: Conversation[]): Conversation[] {\r\n    return data.map((conversation) => {\r\n      const sortedMessages = [...conversation.messages].sort((a, b) => {\r\n        const dateA = moment(a.createdAt).valueOf();\r\n        const dateB = moment(b.createdAt).valueOf();\r\n        return dateA - dateB;\r\n      });\r\n\r\n      return { ...conversation, messages: sortedMessages };\r\n    });\r\n  }\r\n\r\n  private _getUreadMessageIds(userId: string, messages: Array<Message>) {\r\n    var ids: string[] = [];\r\n    messages.map((m) => {\r\n      if (m.messageState === MessageStates.SENT && m.from !== userId) {\r\n        ids.push(m.messageId);\r\n      }\r\n    });\r\n    return ids;\r\n  }\r\n\r\n  _wsDisconnect(config?: { shouldReconnect: boolean }) {\r\n    try {\r\n      if (this.socket) {\r\n        this.shouldReconnect = config?.shouldReconnect ?? true;\r\n        // this.wsConnected = false;\r\n        const data = JSON.stringify({\r\n          action: ServerActions.CONNECTION_CLOSED,\r\n          message: {\r\n            projectId: this.projectConfig.projectId,\r\n            from: this.userMeta.uid,\r\n            user: this.userMeta\r\n          },\r\n        });\r\n        this.socket.send(data);\r\n        this.socket.close();\r\n        this.conversationMap = {};\r\n        this.conversationListMeta = {};\r\n        this.broadcastListMeta = {}\r\n        this.updateConnectionState(connectionStates.NO_CONNECTION);\r\n        // this.emit(Events.CONNECTION_CHANGED, {\r\n        //   connecting: false,\r\n        //   isConnected: false,\r\n        //   fetchingConversations: false,\r\n        // });\r\n      }\r\n    } catch (error) {\r\n      if(error instanceof Error){\r\n        console.error(error.message)\r\n      }\r\n    }\r\n  }\r\n\r\n  private startHealthCheck() {\r\n    if (this.socket) {\r\n      if (this.healthCheckRef) {\r\n        clearInterval(this.healthCheckRef);\r\n      }\r\n\r\n      // Set the new interval\r\n      this.healthCheckRef = setInterval(() => {\r\n        // Check WebSocket connection status\r\n        if (this.socket?.readyState === WebSocket.OPEN) {\r\n          const data = JSON.stringify({\r\n            action: ServerActions.HEALTH_CHECK,\r\n            message: {\r\n              message: \"Hello!\",\r\n              from: this.userMeta.uid,\r\n              token: this.wsAccessConfig.token,\r\n              user: this.userMeta\r\n            },\r\n          });\r\n          this.socket.send(data); // send the health check message\r\n          this.emit(Events.CONVERSATION_LIST_META_CHANGED, {\r\n            conversationListMeta: this.conversationListMeta,\r\n          });\r\n        }\r\n      }, 30000);\r\n    }\r\n  }\r\n\r\n  private retryConnection() {\r\n    // Retry logic or call _initiateConnection() after delay\r\n    if (this.retry_count >= this.max_retry_count) {\r\n      return console.warn(\r\n        `Connection attempt failed after multiple retries. Please check your network settings or try again.`\r\n      );\r\n    }\r\n    this.updateConnectionState(connectionStates.SOCKET_CONNECTING)\r\n    // this.emit(Events.CONNECTION_CHANGED, {\r\n    //   connecting: true,\r\n    //   isConnected: false,\r\n    //   fetchingConversations: false,\r\n    // });\r\n    if (!this.connectionState.isConnected) {\r\n      this.retryRef = setTimeout(() => {\r\n        this._initiateConnection(this.userMeta);\r\n        this.retry_count += 1;\r\n      }, 5000);\r\n    }\r\n  }\r\n\r\n  private setupEventHandlers() {\r\n    if (this.socket) {\r\n      this.socket.onmessage = (event: MessageEvent) => {\r\n        const msClient = MessageClient.getInstace(this, \"\");\r\n        msClient.messageEventHandler(event);\r\n      };\r\n\r\n      // Handle errors\r\n      this.socket.onerror = (event: ErrorEvent) => {\r\n        // this.wsConnected = false;\r\n        if (this.shouldReconnect) {\r\n          console.error(\"Socket error. Attempting to reconnect... Event: \", event);\r\n          this.retryConnection();\r\n        }\r\n      };\r\n\r\n      // Handle disconnection (socket closes)\r\n      this.socket.onclose = () => {\r\n        // this.wsConnected = false;\r\n        if (this.shouldReconnect) {\r\n          console.warn(\"Socket closed. Attempting to reconnect...\");\r\n          this.retryConnection();\r\n        }\r\n      };\r\n\r\n      this.startHealthCheck();\r\n    }\r\n  }\r\n}\r\n","export enum Errors {\r\n  USER_NOT_INITIATED = 'Unable to call method, call (initializeUser) method first, Err callingfunction: ',\r\n  CONVERSATION_NOT_PREPARED = 'Method newConversation() on conversation was not called'\r\n}\r\n\r\nexport const buildError = (error: keyof typeof Errors, funcName: string) => {\r\n  return Errors[error]+funcName\r\n}\r\n\r\n","import Connection from \"./Connection\";\r\nimport { Errors } from \"./error\";\r\nimport { Events } from \"./events\";\r\nimport {\r\n  AttachmentTypes,\r\n  ConversationListItem,\r\n  ConversationType,\r\n  GroupChatMeta,\r\n  Message,\r\n  MessageStates,\r\n  Participant,\r\n  Prettify,\r\n  SendGroupMessageGenerics,\r\n  SendMessageGenerics,\r\n  ServerActions,\r\n  UserMeta,\r\n} from \"./types\";\r\nimport {\r\n  generateConversationId,\r\n  generateFillerTimestamps,\r\n  generateId,\r\n} from \"./utils\";\r\n\r\nlet userMetaSample = {\r\n  id: \"\",\r\n  username: \"\",\r\n  email: \"\",\r\n  firstname: \"\",\r\n  lastname: \"\",\r\n  profileImgUrl: \"\",\r\n  phone: \"\",\r\n  profileBannerUrl: \"\",\r\n  custom: {},\r\n};\r\nexport default class Conversation {\r\n  private static conversation: Conversation | null = null;\r\n  private connection: Connection;\r\n  private participants: UserMeta[];\r\n  private otherParticipant: UserMeta | null;\r\n  private conversationType: \"group-chat\" | \"private-chat\";\r\n  private groupMeta: GroupChatMeta | null;\r\n\r\n  constructor(\r\n    connection: Connection,\r\n    participantDetails: UserMeta[] | UserMeta,\r\n    groupMeta: GroupChatMeta | null\r\n  ) {\r\n    this.connection = connection;\r\n    this.participants = [];\r\n    this.otherParticipant = null;\r\n    this.conversationType = \"private-chat\";\r\n\r\n    if (Array.isArray(participantDetails)) {\r\n      this.conversationType = \"group-chat\";\r\n      this.participants = participantDetails.map((p) => ({\r\n        ...userMetaSample,\r\n        ...p,\r\n      }));\r\n      this.groupMeta = groupMeta;\r\n    } else {\r\n      this.otherParticipant = { ...userMetaSample, ...participantDetails };\r\n      this.conversationType = \"private-chat\";\r\n      this.groupMeta = null;\r\n    }\r\n  }\r\n\r\n  static getInstance(\r\n    connection: Connection,\r\n    participantDetails: UserMeta[] | UserMeta,\r\n    groupMeta: GroupChatMeta | null\r\n  ): Conversation {\r\n    if (Conversation.conversation) {\r\n      return Conversation.conversation;\r\n    }\r\n    Conversation.conversation = new Conversation(\r\n      connection,\r\n      participantDetails,\r\n      groupMeta\r\n    );\r\n    return Conversation.conversation;\r\n  }\r\n\r\n  private generateConversation(\r\n    conversationId: string,\r\n    participants: UserMeta[],\r\n    message: Message,\r\n    conversationType: \"group-chat\" | \"private-chat\"\r\n  ) {\r\n    const timeStamps = generateFillerTimestamps();\r\n    const participantIds = participants.map((p) => p.uid);\r\n    const senderObject = {\r\n      id: generateId(),\r\n      uid: this.connection.userMeta.uid,\r\n      participantId: this.connection.userMeta.uid,\r\n      participantDetails: {\r\n        ...this.connection.userMeta,\r\n        ...timeStamps,\r\n      },\r\n      ...timeStamps,\r\n    };\r\n\r\n    const updatedParticipantList = participants.map((participant) => ({\r\n      id: generateId(),\r\n      uid: participant.uid,\r\n      participantId: participant.uid,\r\n      participantDetails: {\r\n        ...participant,\r\n        ...timeStamps,\r\n      },\r\n      ...timeStamps,\r\n    }));\r\n\r\n    const participantList = [senderObject, ...updatedParticipantList];\r\n\r\n    return {\r\n      participants: [this.connection.userMeta.uid, ...participantIds],\r\n      admins: [this.connection.userMeta.uid],\r\n      conversationId,\r\n      messages: message.message.length > 0 ? [message] : [],\r\n      conversationType,\r\n      participantList,\r\n      meta: null,\r\n      groupMeta: conversationType === \"group-chat\" ? this.groupMeta : null,\r\n      ...timeStamps,\r\n    };\r\n  }\r\n\r\n  create(text?: string) {\r\n    try {\r\n      const messageId = generateId();\r\n      const groupConversationId = generateId();\r\n\r\n      const fullMessage = {\r\n        messageId,\r\n        from: this.connection.userMeta.uid,\r\n        to: [{}],\r\n        conversationType: this.conversationType,\r\n        groupMeta: this.groupMeta || {\r\n          groupName: \"My group\",\r\n          groupIcon: \"https://picsum.photos/200/300\",\r\n          groupBanner: \"https://picsum.photos/200/300\",\r\n        },\r\n        senderMeta: this.connection.userMeta,\r\n        participantIds: [] as string[],\r\n        message: {\r\n          message: text ? text : \"\",\r\n          messageId,\r\n          messageState: MessageStates.SENT,\r\n          conversationId: \"\",\r\n          from: this.connection.userMeta.uid,\r\n          to: \"\",\r\n          attachmentType: AttachmentTypes.NONE,\r\n          messageOwner: {\r\n            ...this.connection.userMeta,\r\n            meta: this.connection.userMeta,\r\n            ...generateFillerTimestamps(),\r\n          },\r\n          attachedMedia: [],\r\n          quotedMessageId: \"\",\r\n          quotedMessage: null,\r\n          reactions: [],\r\n          lastEdited: null,\r\n          ...generateFillerTimestamps(),\r\n        },\r\n        token: this.connection.wsAccessConfig.token,\r\n      };\r\n\r\n      if (this.conversationType === \"group-chat\") {\r\n        if (this.participants.length === 0) {\r\n          throw new Error(Errors.CONVERSATION_NOT_PREPARED);\r\n        }\r\n\r\n        const participantIds = this.participants.map((p) => p.uid);\r\n        fullMessage.message.conversationId = groupConversationId;\r\n        fullMessage.to = this.participants;\r\n        fullMessage.participantIds = [\r\n          ...participantIds,\r\n          this.connection.userMeta.uid,\r\n        ];\r\n\r\n        this.sendMessage(\r\n          fullMessage,\r\n          groupConversationId,\r\n          this.participants,\r\n          \"group-chat\"\r\n        );\r\n      } else {\r\n        if (!this.otherParticipant) {\r\n          throw new Error(Errors.CONVERSATION_NOT_PREPARED);\r\n        }\r\n\r\n        const privateConversationId = generateConversationId(\r\n          this.connection.userMeta.uid,\r\n          this.otherParticipant.uid,\r\n          this.connection.projectConfig.projectId\r\n        );\r\n\r\n        fullMessage.message.conversationId = privateConversationId;\r\n        fullMessage.message.to = this.otherParticipant.uid;\r\n        fullMessage.to = [this.otherParticipant];\r\n        fullMessage.participantIds = [\r\n          this.otherParticipant.uid,\r\n          this.connection.userMeta.uid,\r\n        ];\r\n\r\n        var res = this.sendMessage(\r\n          fullMessage,\r\n          privateConversationId,\r\n          [this.otherParticipant],\r\n          \"private-chat\"\r\n        );\r\n        return res;\r\n      }\r\n    } catch (error) {\r\n      if (error instanceof Error) {\r\n        console.error(error.message);\r\n      }\r\n    }\r\n  }\r\n\r\n  private sendMessage(\r\n    fullMessage: any,\r\n    conversationId: string,\r\n    participants: UserMeta[],\r\n    type: \"group-chat\" | \"private-chat\"\r\n  ) {\r\n    try {\r\n      const socketMessage = {\r\n        action: ServerActions.CREATE_CONVERSATION,\r\n        message: fullMessage,\r\n        user: this.connection.userMeta,\r\n      };\r\n      var result: ConversationListItem;\r\n      if (this.connection.socket) {\r\n        this.connection.socket.send(JSON.stringify(socketMessage));\r\n        if (!this.connection.conversationListMeta[conversationId]) {\r\n          const conversation = this.generateConversation(\r\n            conversationId,\r\n            participants,\r\n            fullMessage.message,\r\n            type\r\n          );\r\n\r\n          var hasMessage = fullMessage.message.message.length > 0;\r\n\r\n          this.connection.conversationListMeta[conversationId] = {\r\n            conversation,\r\n            lastMessage: hasMessage ? fullMessage.message : null,\r\n            unread: [],\r\n          };\r\n          result = {\r\n            conversation,\r\n            lastMessage: fullMessage.message,\r\n            unread: [],\r\n          };\r\n        } else {\r\n          // check tthis out\r\n          const prevConversation =\r\n            this.connection.conversationListMeta[conversationId];\r\n          var messages = [...prevConversation.conversation.messages];\r\n\r\n          // check if the user created the conversation with an initial message.\r\n          if (fullMessage.message.message.length > 0) {\r\n            messages.unshift(fullMessage.message);\r\n          }\r\n          var updatedConversationListMeta = {\r\n            conversation: { ...prevConversation.conversation, messages },\r\n            lastMessage: fullMessage.message,\r\n            unread: [],\r\n          };\r\n          this.connection.conversationListMeta[conversationId] =\r\n            updatedConversationListMeta;\r\n          result = updatedConversationListMeta;\r\n        }\r\n\r\n        this.connection.emit(Events.CONVERSATION_LIST_META_CHANGED, {\r\n          conversationListMeta: this.connection.conversationListMeta,\r\n        });\r\n        this.reset();\r\n        return result;\r\n      }\r\n    } catch (error) {\r\n      if(error instanceof Error){\r\n        console.error(error.message)\r\n      }\r\n    }\r\n  }\r\n\r\n  reset() {\r\n    Conversation.conversation = null;\r\n  }\r\n}\r\n","import BroadcastList from \"./Broadcast\";\r\nimport Connection, { ConnectionState, connectionStates } from \"./Connection\";\r\nimport Conversation from \"./Conversation\";\r\nimport MessageClient from \"./MessageClient\";\r\nimport { buildError } from \"./error\";\r\nimport { Events } from \"./events\";\r\nimport {\r\n  Config,\r\n  ConversationListMeta,\r\n  GroupChatMeta,\r\n  UserMeta,\r\n} from \"./types\";\r\nimport WebSocket from \"isomorphic-ws\";\r\n\r\ntype InitializeUser = {\r\n  data: UserMeta, \r\n  config?: { \r\n    notificationConfig?: NotificationConfig, \r\n    connectionConfig?: { \r\n      reset: boolean \r\n    } \r\n  }\r\n}\r\n\r\nexport type NotificationConfig = {\r\n  type: \"expo\" | \"fcm\" | \"apns\" | null\r\n  token: string | null \r\n}\r\n\r\nexport default class ChatClient {\r\n  private static client_instance: ChatClient;\r\n  private connection: Connection | null;\r\n  subId: string;\r\n  projectId: string;\r\n  chatUserId: string;\r\n  // userMeta: UserMeta;\r\n\r\n  constructor(subId: string, projectId: string) {\r\n    this.subId = subId;\r\n    this.projectId = projectId;\r\n    // this.userMeta = defaultUser, \r\n    this.chatUserId = '';\r\n    this.connection = null;\r\n  }\r\n\r\n\r\n  static getInstance({ projectId, subId }: Config) {\r\n    if (!ChatClient.client_instance) {\r\n      ChatClient.client_instance = new ChatClient(subId, projectId);\r\n      return ChatClient.client_instance\r\n    }\r\n    return ChatClient.client_instance\r\n  }\r\n\r\n  initializeUser(data: UserMeta, config?: { notificationConfig?: NotificationConfig, connectionConfig?: { reset: boolean } }) {\r\n    if (data) {\r\n      if (ChatClient.client_instance) {\r\n        const conn = Connection.getInstance(ChatClient.client_instance);\r\n        this.connection = conn;\r\n        this.connection.updateConnectionState(connectionStates.GETTING_CONVERSATIONS);\r\n        conn._initiateConnection(data, config);\r\n        this.chatUserId = data.uid\r\n      }\r\n    }\r\n  }\r\n\r\n  disconnect() {\r\n    if (this.connection) {\r\n      return this.connection._wsDisconnect({ shouldReconnect: false });\r\n    } else {\r\n      throw new Error(buildError(\"USER_NOT_INITIATED\", \"disconnect\"));\r\n    }\r\n  }\r\n\r\n  retryConnection() {\r\n    if (this.connection) {\r\n      // return this.connection._retryConnection();\r\n      if (this.connection.socket?.readyState !== WebSocket.OPEN) {\r\n        console.info(\"Retrying connection...\");\r\n        if (this.connection.userMeta) {\r\n          this.connection.emit(Events.CONNECTION_CHANGED, {\r\n            connecting: true,\r\n            isConnected: false,\r\n            fetchingConversations: true,\r\n          });\r\n          this.connection._initiateConnection(this.connection.userMeta, { connectionConfig: { reset: true }, notificationConfig: this.connection.notificationConfig });\r\n        }\r\n      }\r\n    } else {\r\n      throw new Error(buildError(\"USER_NOT_INITIATED\", \"retryConnection\"));\r\n    }\r\n  }\r\n\r\n  getConnectionStatus(): ConnectionState {\r\n    if (this.connection) {\r\n      return this.connection.connectionState\r\n    } else {\r\n      return connectionStates.NO_CONNECTION\r\n    }\r\n  }\r\n\r\n  subscribe(event: string, func: (event: any) => void) {\r\n    if (this.connection) {\r\n      this.connection.on(event, func);\r\n    } else {\r\n      throw new Error(\r\n        \"Unable to subscribe for events, create a connection first\"\r\n      );\r\n    }\r\n  }\r\n\r\n  unsubscribe(event: string, func: (event: any) => void) {\r\n    if (this.connection) {\r\n      this.connection.off(event, func);\r\n    }\r\n  }\r\n\r\n  unsubscribeAll(event: string) {\r\n    if (this.connection) {\r\n      this.connection.removeAllListeners(event);\r\n    }\r\n  }\r\n\r\n  getConversations(): ConversationListMeta {\r\n    if(this.connection) {\r\n      return JSON.parse(JSON.stringify(this.connection.conversationListMeta))\r\n    }else{\r\n      console.warn(\"No connection available, initialize user before calling method\")\r\n      return {}\r\n    }\r\n  }\r\n\r\n  getBroadcastLists(): ConversationListMeta {\r\n    if(this.connection) {\r\n      return JSON.parse(JSON.stringify(this.connection.broadcastListMeta))\r\n    }else{\r\n      console.warn(\"No connection available, initialize user before calling method\")\r\n      return {}\r\n    }\r\n  }\r\n\r\n  newConversation(participantDetails: UserMeta[] | UserMeta, groupMeta: GroupChatMeta | null): Conversation {\r\n    if(this.connection) {\r\n      const conversation = Conversation.getInstance(this.connection, participantDetails, groupMeta);\r\n      return conversation\r\n    }else{\r\n      throw new Error(\"No connection available\")\r\n    }\r\n  }\r\n\r\n  newBroadcastList(participantDetails: UserMeta[]): BroadcastList {\r\n    if(this.connection) {\r\n      const broadcast = BroadcastList.getInstance(this.connection, participantDetails);\r\n      return broadcast\r\n    }else{\r\n      throw new Error(\"No connection available\")\r\n    }\r\n  }\r\n\r\n  messageClient(conversationId: string) {\r\n    if (this.connection) {\r\n      const msClient = MessageClient.getInstace(this.connection, conversationId);\r\n      return {\r\n        getMessages: msClient.getMessages.bind(msClient),\r\n        getBroadcastListMessages: msClient.getBroadcastListMessages.bind(msClient),\r\n        getConversation: msClient.getConversation.bind(msClient),\r\n        sendMessage: msClient.sendMessage.bind(msClient),\r\n        broadcastMessage: msClient.broadcastMessage.bind(msClient),\r\n        editMessage: msClient.editMessage.bind(msClient),\r\n        sendTypingNotification: msClient.sendTypingNotification.bind(msClient),\r\n        sendStoppedTypingNotification: msClient.sendStoppedTypingNotification.bind(msClient),\r\n        reactToMessage: msClient.reactToMessage.bind(msClient),\r\n        // uploadAttachment: msClient.uploadAttachment.bind(msClient),\r\n        // uploadAttachmentV2: msClient.uploadAttachmentV2.bind(msClient),\r\n        uploadFile: msClient.uploadFile.bind(msClient),\r\n        setActiveConversation: msClient.setActiveConversation.bind(msClient),\r\n        unSetActiveConversation: msClient.unSetActiveConversation.bind(msClient),\r\n        getEmojiList: msClient.getEmojiList.bind(msClient),\r\n        deleteMessage: msClient.deleteMessage.bind(msClient),\r\n        readMessages: msClient.readMessages.bind(msClient),\r\n      }\r\n    } else {\r\n      throw new Error(\"No connection available\");\r\n    }\r\n  }\r\n}\r\n\r\n"],"mappings":"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","names":["moment","murmurHash3_x64_64","str","seed","h1","h2","c1","c2","length","remainder","bytes","i","k1","k2","generateConversationId","str1","str2","projectId","combinedString","generateId","uuid","characters","randomNumber","character","generateFillerTimestamps","_BroadcastList","connection","participants","name","conversationId","timeStamps","generateFillerTimestamps","participantIds","p","senderObject","generateId","updatedParticipantList","participant","participantList","newConveration","socketMessage","error","BroadcastList","axios","API","chatApi","payload","response","axios","error","CREATE_SESSION","userId","subId","projectId","API","GET_CONVERSATIONS","token","GET_CONVERSATION","conversationId","GET_BROADCASTLISTS","GET_MESSAGES","page","GET_BROADCAST_LIST_MESSAGES","broadcastListId","GET_EMOJIS","UPLOAD_MEDIA","data","GET_PRESIGNED_URL","moment","CLEAR_UNREAD_TIMEOUT","MessageClient","_MessageClient","connection","conversationId","messageList","message","list","action","newMessage","socketMessage","conversationMeta","updatedMessages","unread","error","isBroadcast","updatedMessage","messageId","prevMessage","m","editedMessage","updatedMessageList","reactions","config","reactionPayload","prevLastMessage","updatedConversationListMeta","data","conversation","uid","screen","emit","ids","i","len","isLastMessage","filteredMessages","newLastMessage","to","generateId","timeStamps","generateFillerTimestamps","messageOwner","messageStruct","payload","broadcastListId","participantsIds","broadcastItem","messages","updatedBroadCastItem","p","generateConversationId","prevConversation","page","response","GET_MESSAGES","a","b","dateA","dateB","err","GET_BROADCAST_LIST_MESSAGES","GET_CONVERSATION","GET_EMOJIS","base64","fileKey","UPLOAD_MEDIA","uri","meta","res","GET_PRESIGNED_URL","body","fileSize","chunks","totalSize","chunk","buffer","mediaType","mimeType","event","wsData","incomingMessagePayload","readMessagesPayload","incomingMessage","existingConversation","newConversationId","newConversation","newConversationMeta","userTypingPayload","messageReactionPayload","errorPayload","deletedMessage","WebSocket","EventEmitter","moment","defaultUser","connectionStates","Connection","_Connection","EventEmitter","client_instance","defaultUser","state","token","response","GET_CONVERSATIONS","conversationListMeta","acc","conversation","sortedConversation","messages","lastMessage","conversationMap","err","GET_BROADCASTLISTS","broadcastListMeta","user","config","res","CREATE_SESSION","message","WebSocket","ws","error","sorted","a","b","dateA","data","sortedMessages","moment","dateB","userId","ids","m","event","MessageClient","Errors","buildError","error","funcName","userMetaSample","_Conversation","connection","participantDetails","groupMeta","p","conversationId","participants","message","conversationType","timeStamps","generateFillerTimestamps","participantIds","senderObject","generateId","updatedParticipantList","participant","participantList","text","messageId","groupConversationId","fullMessage","privateConversationId","generateConversationId","res","error","type","socketMessage","result","prevConversation","messages","updatedConversationListMeta","conversation","hasMessage","Conversation","WebSocket","ChatClient","_ChatClient","subId","projectId","data","config","conn","Connection","connectionStates","buildError","event","func","participantDetails","groupMeta","Conversation","BroadcastList","conversationId","msClient","MessageClient"]}