@ermis-network/ermis-chat-sdk 1.0.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -217,11 +217,25 @@ function addToMessageList(messages, message, timestampChanged = false, sortBy =
217
217
  }
218
218
  if (!timestampChanged && message.id) {
219
219
  if (messageArr[left] && message.id === messageArr[left].id) {
220
- messageArr[left] = message;
220
+ const existingMessage = messageArr[left];
221
+ const mergedMessage = { ...existingMessage };
222
+ Object.keys(message).forEach((key) => {
223
+ if (message[key] !== void 0) {
224
+ mergedMessage[key] = message[key];
225
+ }
226
+ });
227
+ messageArr[left] = mergedMessage;
221
228
  return [...messageArr];
222
229
  }
223
230
  if (messageArr[left - 1] && message.id === messageArr[left - 1].id) {
224
- messageArr[left - 1] = message;
231
+ const existingMessage = messageArr[left - 1];
232
+ const mergedMessage = { ...existingMessage };
233
+ Object.keys(message).forEach((key) => {
234
+ if (message[key] !== void 0) {
235
+ mergedMessage[key] = message[key];
236
+ }
237
+ });
238
+ messageArr[left - 1] = mergedMessage;
225
239
  return [...messageArr];
226
240
  }
227
241
  }
@@ -330,7 +344,7 @@ var createPacketWithHeader = (data, timestamp, type, configMsg) => {
330
344
  const jsonString = JSON.stringify(configMsg);
331
345
  const encoder = new TextEncoder();
332
346
  payload = encoder.encode(jsonString);
333
- } else if (type === "connected") {
347
+ } else if (type === "connected" || type === "healthCall") {
334
348
  HEADER_SIZE = 1;
335
349
  payload = new Uint8Array(0);
336
350
  } else {
@@ -361,6 +375,9 @@ var createPacketWithHeader = (data, timestamp, type, configMsg) => {
361
375
  case "transciverState":
362
376
  typeCode = 7;
363
377
  break;
378
+ case "healthCall":
379
+ typeCode = 11;
380
+ break;
364
381
  }
365
382
  packet[0] = typeCode;
366
383
  if (timestamp !== null) {
@@ -685,8 +702,12 @@ var ChannelState = class {
685
702
  }
686
703
  }
687
704
  };
688
- this.messageSets.forEach((set) => _updateUserMessages(set.messages, user));
705
+ this.messageSets.forEach((set) => {
706
+ _updateUserMessages(set.messages, user);
707
+ set.messages = [...set.messages];
708
+ });
689
709
  _updateUserMessages(this.pinnedMessages, user);
710
+ this.pinnedMessages = [...this.pinnedMessages];
690
711
  };
691
712
  deleteUserMessages = (user, hardDelete = false) => {
692
713
  const _deleteUserMessages = (messages, user2, hardDelete2 = false) => {
@@ -1531,9 +1552,13 @@ var Channel = class {
1531
1552
  state.pinned_messages = state.pinned_messages ? enrichWithUserInfo(state.pinned_messages, users) : [];
1532
1553
  state.read = enrichWithUserInfo(state.read || [], users);
1533
1554
  state.channel.is_pinned = state.is_pinned || false;
1534
- if (!this.id) {
1555
+ const oldCid = this.cid;
1556
+ if (oldCid !== state.channel.cid) {
1535
1557
  this.id = state.channel.id;
1536
1558
  this.cid = state.channel.cid;
1559
+ if (oldCid in this.getClient().activeChannels) {
1560
+ delete this.getClient().activeChannels[oldCid];
1561
+ }
1537
1562
  const membersStr = state.channel.members.map((member) => member.user_id || member.user?.id).sort().join(",");
1538
1563
  const tempChannelCid = `${this.type}:!members-${membersStr}`;
1539
1564
  if (tempChannelCid in this.getClient().activeChannels) {
@@ -1542,6 +1567,8 @@ var Channel = class {
1542
1567
  if (!(this.cid in this.getClient().activeChannels)) {
1543
1568
  this.getClient().activeChannels[this.cid] = this;
1544
1569
  }
1570
+ } else if (!(this.cid in this.getClient().activeChannels)) {
1571
+ this.getClient().activeChannels[this.cid] = this;
1545
1572
  }
1546
1573
  const { messageSet } = this._initializeState(state, messageSetToAddToIfDoesNotExist);
1547
1574
  const areCapabilitiesChanged = [...state.channel.own_capabilities || []].sort().join() !== [...Array.isArray(this.data?.own_capabilities) ? this.data?.own_capabilities : []].sort().join();
@@ -1680,55 +1707,77 @@ var Channel = class {
1680
1707
  }
1681
1708
  async getThumbBlobVideo(file) {
1682
1709
  return new Promise((resolve) => {
1683
- const seekTo = 0.1;
1684
1710
  const videoPlayer = document.createElement("video");
1685
1711
  videoPlayer.src = URL.createObjectURL(file);
1686
1712
  videoPlayer.crossOrigin = "anonymous";
1713
+ videoPlayer.muted = true;
1687
1714
  videoPlayer.load();
1715
+ let attempts = 0;
1716
+ const maxAttempts = 5;
1717
+ const seekInterval = 1;
1718
+ const cleanup = () => {
1719
+ URL.revokeObjectURL(videoPlayer.src);
1720
+ videoPlayer.remove();
1721
+ };
1688
1722
  videoPlayer.addEventListener("error", () => {
1689
1723
  console.error("Error when loading video file.");
1724
+ cleanup();
1690
1725
  resolve(null);
1691
1726
  });
1692
- videoPlayer.addEventListener("loadedmetadata", () => {
1693
- if (videoPlayer.duration < seekTo) {
1694
- console.error("Video is too short.");
1695
- resolve(null);
1696
- return;
1697
- }
1698
- setTimeout(() => {
1699
- videoPlayer.currentTime = seekTo;
1700
- }, 200);
1701
- });
1702
- videoPlayer.addEventListener("seeked", () => {
1727
+ const captureFrame = () => {
1703
1728
  try {
1704
1729
  const canvas = document.createElement("canvas");
1705
1730
  canvas.width = videoPlayer.videoWidth;
1706
1731
  canvas.height = videoPlayer.videoHeight;
1707
- const ctx = canvas.getContext("2d");
1732
+ const ctx = canvas.getContext("2d", { willReadFrequently: true });
1708
1733
  if (!ctx) {
1709
1734
  console.error("Failed to create canvas context.");
1735
+ cleanup();
1710
1736
  resolve(null);
1711
1737
  return;
1712
1738
  }
1713
1739
  ctx.drawImage(videoPlayer, 0, 0, canvas.width, canvas.height);
1714
- ctx.canvas.toBlob(
1740
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
1741
+ const data = imageData.data;
1742
+ let totalLuminance = 0;
1743
+ const sampleStep = 40;
1744
+ let samples = 0;
1745
+ for (let i = 0; i < data.length; i += sampleStep * 4) {
1746
+ const r = data[i];
1747
+ const g = data[i + 1];
1748
+ const b = data[i + 2];
1749
+ totalLuminance += 0.2126 * r + 0.7152 * g + 0.0722 * b;
1750
+ samples++;
1751
+ }
1752
+ const avgLuminance = totalLuminance / samples;
1753
+ if (avgLuminance < 15 && attempts < maxAttempts && videoPlayer.currentTime + seekInterval < videoPlayer.duration) {
1754
+ attempts++;
1755
+ videoPlayer.currentTime += seekInterval;
1756
+ return;
1757
+ }
1758
+ canvas.toBlob(
1715
1759
  (blob) => {
1760
+ cleanup();
1716
1761
  if (!blob) {
1717
1762
  console.error("Failed to generate thumbnail.");
1718
1763
  resolve(null);
1719
1764
  return;
1720
1765
  }
1721
1766
  resolve(blob);
1722
- URL.revokeObjectURL(videoPlayer.src);
1723
1767
  },
1724
1768
  "image/jpeg",
1725
1769
  0.75
1726
1770
  );
1727
1771
  } catch (error) {
1728
1772
  console.error("Error while extracting thumbnail:", error);
1773
+ cleanup();
1729
1774
  resolve(null);
1730
1775
  }
1776
+ };
1777
+ videoPlayer.addEventListener("loadedmetadata", () => {
1778
+ videoPlayer.currentTime = Math.min(0.5, videoPlayer.duration);
1731
1779
  });
1780
+ videoPlayer.addEventListener("seeked", captureFrame);
1732
1781
  });
1733
1782
  }
1734
1783
  async enableTopics() {
@@ -1861,21 +1910,50 @@ var Channel = class {
1861
1910
  if (event.message) {
1862
1911
  this._extendEventWithOwnReactions(event);
1863
1912
  channelState.removeMessage(event.message);
1864
- channelState.addMessageSorted(event.message, false, false);
1913
+ if (channelState.latestMessages.length === 0) {
1914
+ this.query({ messages: { limit: 1 } }).then(() => {
1915
+ this._callChannelListeners({
1916
+ type: "channel.updated",
1917
+ cid: this.cid,
1918
+ channel: this.data
1919
+ });
1920
+ }).catch((err) => {
1921
+ this._client.logger("error", "Failed to query for new last message after deletion", { err });
1922
+ });
1923
+ }
1865
1924
  channelState.removeQuotedMessageReferences(event.message);
1866
1925
  if ([...channelState.pinnedMessages].some((msg) => msg.id === event.message?.id)) {
1867
1926
  channelState.removePinnedMessage(event.message);
1868
1927
  }
1928
+ const msgTime = event.message.created_at ? new Date(event.message.created_at) : null;
1869
1929
  for (const userId in channelState.read) {
1870
1930
  if (userId !== event.user?.id && event.message.id === channelState.read[userId].last_read_message_id) {
1871
1931
  channelState.read[userId] = { ...channelState.read[userId], last_read_message_id: void 0 };
1872
1932
  }
1933
+ const userRead = channelState.read[userId];
1934
+ const lastRead = userRead.last_read ? new Date(userRead.last_read) : /* @__PURE__ */ new Date(0);
1935
+ if (msgTime && msgTime > lastRead) {
1936
+ const wasSentByUser = event.message.user?.id === userId || event.message.user_id === userId;
1937
+ const isSystem = event.message.type === "system";
1938
+ if (!wasSentByUser && !isSystem) {
1939
+ userRead.unread_messages = Math.max(0, userRead.unread_messages - 1);
1940
+ if (userId === this.getClient().userID) {
1941
+ channelState.unreadCount = Math.max(0, channelState.unreadCount - 1);
1942
+ }
1943
+ }
1944
+ }
1873
1945
  }
1874
1946
  }
1875
1947
  break;
1876
1948
  case "message.deleted_for_me":
1877
1949
  if (event.message) {
1878
- channelState.removeMessage(event.message);
1950
+ delete event.message.user;
1951
+ delete event.message.user_id;
1952
+ event.message.display_type = "deleted";
1953
+ event.message.pinned_at = null;
1954
+ event.message.updated_at = null;
1955
+ event.message.status = "received";
1956
+ channelState.addMessageSorted(event.message);
1879
1957
  channelState.removeQuotedMessageReferences(event.message);
1880
1958
  if ([...channelState.pinnedMessages].some((msg) => msg.id === event.message?.id)) {
1881
1959
  channelState.removePinnedMessage(event.message);
@@ -1961,9 +2039,10 @@ var Channel = class {
1961
2039
  channelState.addMessageSorted(event.message, false, false);
1962
2040
  }
1963
2041
  break;
1964
- case "channel.truncate":
1965
- if (event.channel?.created_at) {
1966
- const truncatedAt = +new Date(event.channel.created_at);
2042
+ case "channel.truncate": {
2043
+ const truncateDate = event.channel?.created_at || event.created_at;
2044
+ if (truncateDate) {
2045
+ const truncatedAt = +new Date(truncateDate);
1967
2046
  channelState.messageSets.forEach((messageSet, messageSetIndex) => {
1968
2047
  messageSet.messages.forEach(({ created_at: createdAt, id }) => {
1969
2048
  if (truncatedAt > +createdAt) channelState.removeMessage({ id, messageSetIndex });
@@ -1984,6 +2063,7 @@ var Channel = class {
1984
2063
  }
1985
2064
  }
1986
2065
  break;
2066
+ }
1987
2067
  case "member.added":
1988
2068
  if (event.member?.user_id) {
1989
2069
  const user = getUserInfo(event.member.user_id, users);
@@ -2014,12 +2094,14 @@ var Channel = class {
2014
2094
  channel.data.topics_enabled = true;
2015
2095
  }
2016
2096
  channelState.topics = channelState.topics || [];
2097
+ event.user = getUserInfo(event.user?.id || "", users);
2017
2098
  break;
2018
2099
  case "channel.topic.disabled":
2019
2100
  if (channel.data) {
2020
2101
  channel.data.topics_enabled = false;
2021
2102
  }
2022
2103
  channelState.topics = [];
2104
+ event.user = getUserInfo(event.user?.id || "", users);
2023
2105
  break;
2024
2106
  case "channel.updated":
2025
2107
  if (event.channel) {
@@ -2135,18 +2217,6 @@ var Channel = class {
2135
2217
  channel.data.is_pinned = false;
2136
2218
  }
2137
2219
  break;
2138
- case "channel.topic.disabled":
2139
- if (channel.data) {
2140
- channel.data.topics_enabled = false;
2141
- }
2142
- event.user = getUserInfo(event.user?.id || "", users);
2143
- break;
2144
- case "channel.topic.enabled":
2145
- if (channel.data) {
2146
- channel.data.topics_enabled = true;
2147
- }
2148
- event.user = getUserInfo(event.user?.id || "", users);
2149
- break;
2150
2220
  case "channel.topic.created":
2151
2221
  const members = event.channel?.members || [];
2152
2222
  const enrichedMembers = enrichWithUserInfo(members, users);
@@ -2840,6 +2910,7 @@ var CallAction = /* @__PURE__ */ ((CallAction2) => {
2840
2910
  return CallAction2;
2841
2911
  })(CallAction || {});
2842
2912
  var CallStatus = /* @__PURE__ */ ((CallStatus2) => {
2913
+ CallStatus2["PREPARING"] = "preparing";
2843
2914
  CallStatus2["RINGING"] = "ringing";
2844
2915
  CallStatus2["ENDED"] = "ended";
2845
2916
  CallStatus2["CONNECTED"] = "connected";
@@ -2858,6 +2929,7 @@ var FRAME_TYPE = /* @__PURE__ */ ((FRAME_TYPE2) => {
2858
2929
  FRAME_TYPE2[FRAME_TYPE2["REQUEST_CONFIG"] = 8] = "REQUEST_CONFIG";
2859
2930
  FRAME_TYPE2[FRAME_TYPE2["REQUEST_KEY_FRAME"] = 9] = "REQUEST_KEY_FRAME";
2860
2931
  FRAME_TYPE2[FRAME_TYPE2["END_CALL"] = 10] = "END_CALL";
2932
+ FRAME_TYPE2[FRAME_TYPE2["HEALTH_CALL"] = 11] = "HEALTH_CALL";
2861
2933
  return FRAME_TYPE2;
2862
2934
  })(FRAME_TYPE || {});
2863
2935
 
@@ -3051,7 +3123,11 @@ var ErmisChat = class _ErmisChat {
3051
3123
  this.userID = connectionUser.id;
3052
3124
  const setTokenPromise = this._setToken(connectionUser, connectionToken);
3053
3125
  this._setUser(connectionUser);
3054
- this.state.updateUser({ id: connectionUser.id, name: connectionUser?.name || connectionUser.id, avatar: connectionUser?.avatar || "" });
3126
+ this.state.updateUser({
3127
+ id: connectionUser.id,
3128
+ name: connectionUser?.name || connectionUser.id,
3129
+ avatar: connectionUser?.avatar || ""
3130
+ });
3055
3131
  const wsPromise = this.openConnection();
3056
3132
  this.setUserPromise = Promise.all([setTokenPromise, wsPromise]).then(
3057
3133
  (result) => result[1]
@@ -3060,6 +3136,16 @@ var ErmisChat = class _ErmisChat {
3060
3136
  try {
3061
3137
  const result = await this.setUserPromise;
3062
3138
  await this.connectToSSE();
3139
+ this.queryUser(connectionUser.id).then((fullProfile) => {
3140
+ this.user = { ...this.user, ...fullProfile };
3141
+ this.state.updateUser(this.user);
3142
+ this.dispatchEvent({
3143
+ type: "user.updated",
3144
+ me: this.user
3145
+ });
3146
+ }).catch((err) => {
3147
+ this.logger("error", "client:connectUser() - failed to fetch full user profile", { err });
3148
+ });
3063
3149
  return result;
3064
3150
  } catch (err) {
3065
3151
  this.disconnectUser();
@@ -3266,10 +3352,11 @@ var ErmisChat = class _ErmisChat {
3266
3352
  * @returns A Blob of the file content.
3267
3353
  */
3268
3354
  async downloadMedia(url) {
3269
- const response = await this.axiosInstance.get(url, {
3270
- responseType: "blob"
3271
- });
3272
- return response.data;
3355
+ const response = await fetch(url, { cache: "no-store" });
3356
+ if (!response.ok) {
3357
+ throw new Error(`Failed to download media: ${response.statusText}`);
3358
+ }
3359
+ return await response.blob();
3273
3360
  }
3274
3361
  errorFromResponse(response) {
3275
3362
  let err;
@@ -3349,21 +3436,67 @@ var ErmisChat = class _ErmisChat {
3349
3436
  this.dispatchEvent(event);
3350
3437
  };
3351
3438
  _updateMemberWatcherReferences = (user) => {
3352
- const refMap = this.state.userChannelReferences[user.id] || {};
3353
- for (const channelID in refMap) {
3354
- const channel = this.activeChannels[channelID];
3439
+ Object.values(this.activeChannels).forEach((channel) => {
3355
3440
  if (channel?.state) {
3441
+ let hasChange = false;
3356
3442
  if (channel.state.members[user.id]) {
3357
- channel.state.members[user.id].user = user;
3443
+ channel.state.members = {
3444
+ ...channel.state.members,
3445
+ [user.id]: {
3446
+ ...channel.state.members[user.id],
3447
+ user
3448
+ }
3449
+ };
3450
+ hasChange = true;
3451
+ if (channel.data?.type === "messaging") {
3452
+ const members = Object.values(channel.state.members);
3453
+ if (members.length === 2) {
3454
+ const otherMember = members.find((m) => m.user?.id !== this.userID);
3455
+ if (otherMember && otherMember.user?.id === user.id) {
3456
+ channel.data.name = user.name || user.id;
3457
+ channel.data.image = user.avatar || "";
3458
+ }
3459
+ }
3460
+ }
3358
3461
  }
3359
3462
  if (channel.state.watchers[user.id]) {
3360
- channel.state.watchers[user.id] = user;
3463
+ channel.state.watchers = {
3464
+ ...channel.state.watchers,
3465
+ [user.id]: user
3466
+ };
3467
+ hasChange = true;
3361
3468
  }
3362
3469
  if (channel.state.read[user.id]) {
3363
- channel.state.read[user.id].user = user;
3470
+ channel.state.read = {
3471
+ ...channel.state.read,
3472
+ [user.id]: {
3473
+ ...channel.state.read[user.id],
3474
+ user
3475
+ }
3476
+ };
3477
+ hasChange = true;
3478
+ }
3479
+ if (hasChange) {
3480
+ channel._callChannelListeners({
3481
+ type: "channel.updated",
3482
+ channel: channel.data,
3483
+ cid: channel.cid
3484
+ });
3485
+ if (channel.state.members[user.id]) {
3486
+ channel._callChannelListeners({
3487
+ type: "member.updated",
3488
+ member: channel.state.members[user.id],
3489
+ cid: channel.cid
3490
+ });
3491
+ }
3492
+ channel._callChannelListeners({
3493
+ type: "user.updated",
3494
+ user,
3495
+ cid: channel.cid
3496
+ });
3364
3497
  }
3365
3498
  }
3366
- }
3499
+ });
3367
3500
  };
3368
3501
  _updateUserReferences = this._updateMemberWatcherReferences;
3369
3502
  _updateUserMessageReferences = (user) => {
@@ -3373,6 +3506,19 @@ var ErmisChat = class _ErmisChat {
3373
3506
  if (!channel) continue;
3374
3507
  const state = channel.state;
3375
3508
  state?.updateUserMessages(user);
3509
+ channel._callChannelListeners({
3510
+ type: "channel.updated",
3511
+ channel: channel.data,
3512
+ cid: channel.cid
3513
+ });
3514
+ const lastMessage = state?.messages[state.messages.length - 1];
3515
+ if (lastMessage) {
3516
+ channel._callChannelListeners({
3517
+ type: "message.updated",
3518
+ message: lastMessage,
3519
+ cid: channel.cid
3520
+ });
3521
+ }
3376
3522
  }
3377
3523
  };
3378
3524
  _deleteUserMessageReference = (user, hardDelete = false) => {
@@ -3438,7 +3584,11 @@ var ErmisChat = class _ErmisChat {
3438
3584
  const bTime = bLatest ? new Date(bLatest).getTime() : 0;
3439
3585
  return bTime - aTime;
3440
3586
  });
3441
- parentChannel._callChannelListeners({ ...event, type: "channel.updated", channel: parentChannel.data });
3587
+ parentChannel._callChannelListeners({
3588
+ ...event,
3589
+ type: "channel.updated",
3590
+ channel: parentChannel.data
3591
+ });
3442
3592
  }
3443
3593
  }
3444
3594
  });
@@ -3449,7 +3599,9 @@ var ErmisChat = class _ErmisChat {
3449
3599
  if (parentCid && this.activeChannels[parentCid]) {
3450
3600
  const parentChannel = this.activeChannels[parentCid];
3451
3601
  if (parentChannel.state?.topics && event.channel) {
3452
- const topicIndex = parentChannel.state.topics.findIndex((t) => t.cid === event.cid || t.channel?.cid === event.cid);
3602
+ const topicIndex = parentChannel.state.topics.findIndex(
3603
+ (t) => t.cid === event.cid || t.channel?.cid === event.cid
3604
+ );
3453
3605
  if (topicIndex !== -1) {
3454
3606
  const t = parentChannel.state.topics[topicIndex];
3455
3607
  if (t.data) {
@@ -3460,14 +3612,22 @@ var ErmisChat = class _ErmisChat {
3460
3612
  Object.assign(t, event.channel);
3461
3613
  }
3462
3614
  }
3463
- parentChannel._callChannelListeners({ ...event, type: "channel.updated", channel: parentChannel.data });
3615
+ parentChannel._callChannelListeners({
3616
+ ...event,
3617
+ type: "channel.updated",
3618
+ channel: parentChannel.data
3619
+ });
3464
3620
  }
3465
3621
  }
3466
3622
  if (event.cid && this.activeChannels[event.cid]) {
3467
3623
  const topicChannel = this.activeChannels[event.cid];
3468
3624
  if (event.channel) {
3469
3625
  topicChannel.data = { ...topicChannel.data, ...event.channel };
3470
- topicChannel._callChannelListeners({ ...event, type: "channel.updated", channel: topicChannel.data });
3626
+ topicChannel._callChannelListeners({
3627
+ ...event,
3628
+ type: "channel.updated",
3629
+ channel: topicChannel.data
3630
+ });
3471
3631
  }
3472
3632
  }
3473
3633
  });
@@ -3479,14 +3639,20 @@ var ErmisChat = class _ErmisChat {
3479
3639
  if (parentCid && this.activeChannels[parentCid]) {
3480
3640
  const parentChannel = this.activeChannels[parentCid];
3481
3641
  if (parentChannel.state?.topics) {
3482
- const topicIndex = parentChannel.state.topics.findIndex((t) => t.cid === event.cid || t.channel?.cid === event.cid);
3642
+ const topicIndex = parentChannel.state.topics.findIndex(
3643
+ (t) => t.cid === event.cid || t.channel?.cid === event.cid
3644
+ );
3483
3645
  if (topicIndex !== -1) {
3484
3646
  const t = parentChannel.state.topics[topicIndex];
3485
3647
  if (t.data) t.data.is_closed_topic = isClosed;
3486
3648
  else if (t.channel) t.channel.is_closed_topic = isClosed;
3487
3649
  else t.is_closed_topic = isClosed;
3488
3650
  }
3489
- parentChannel._callChannelListeners({ ...event, type: "channel.updated", channel: parentChannel.data });
3651
+ parentChannel._callChannelListeners({
3652
+ ...event,
3653
+ type: "channel.updated",
3654
+ channel: parentChannel.data
3655
+ });
3490
3656
  }
3491
3657
  }
3492
3658
  if (event.cid && this.activeChannels[event.cid]) {
@@ -3542,13 +3708,11 @@ var ErmisChat = class _ErmisChat {
3542
3708
  this.logger("info", `client:recoverState() - Start the querying of ${cids.length} channels`, {
3543
3709
  tags: ["connection", "client"]
3544
3710
  });
3545
- const filter = {
3546
- type: ["messaging", "team"]
3547
- };
3548
- const sort = [];
3549
- const options = {
3550
- message_limit: 25
3551
- };
3711
+ const {
3712
+ filter = { type: ["messaging", "team", "meeting"] },
3713
+ sort = [],
3714
+ options = { message_limit: 1 }
3715
+ } = this.options.recoveryConfig || {};
3552
3716
  await this.queryChannels(filter, sort, options);
3553
3717
  this.logger("info", "client:recoverState() - Querying channels finished", { tags: ["connection", "client"] });
3554
3718
  this.dispatchEvent({
@@ -3610,36 +3774,32 @@ var ErmisChat = class _ErmisChat {
3610
3774
  const data = JSON.parse(event.data);
3611
3775
  this.logger("info", `client:connectToSSE() - SSE message received event : ${JSON.stringify(data)}`, { event });
3612
3776
  if (data.type === "AccountUserChainProjects") {
3613
- let user = {
3614
- name: data.name,
3777
+ const userInfo = {
3615
3778
  id: data.id,
3779
+ name: data.name,
3616
3780
  avatar: data.avatar,
3617
3781
  about_me: data.about_me,
3618
3782
  project_id: data.project_id
3619
3783
  };
3620
- if (this.user?.id === user.id) {
3621
- this.user = { ...this.user, ...user };
3784
+ if (this.user?.id === userInfo.id) {
3785
+ this.user = { ...this.user, ...userInfo };
3622
3786
  }
3623
- this.state.updateUser(user);
3624
- const userInfo = {
3625
- id: user.id,
3626
- name: user.name ? user.name : user.id,
3627
- avatar: user?.avatar || ""
3787
+ this.state.updateUser(userInfo);
3788
+ const minimalUserInfo = {
3789
+ id: userInfo.id,
3790
+ name: userInfo.name || userInfo.id,
3791
+ avatar: userInfo.avatar || ""
3628
3792
  };
3629
- this._updateMemberWatcherReferences(userInfo);
3630
- this._updateUserMessageReferences(userInfo);
3631
- Object.values(this.activeChannels).forEach((channel) => {
3632
- if (channel.data?.type === "messaging" && Object.keys(channel.state.members).length === 2) {
3633
- const otherMember = Object.values(channel.state.members).find((member) => member.user?.id !== this.userID);
3634
- if (otherMember && otherMember.user?.id === user.id) {
3635
- channel.data.name = user.name || user.id;
3636
- channel.data.image = user.avatar || "";
3637
- }
3638
- }
3639
- });
3793
+ this._updateMemberWatcherReferences(minimalUserInfo);
3794
+ this._updateUserMessageReferences(minimalUserInfo);
3640
3795
  if (onCallBack) {
3641
3796
  onCallBack(data);
3642
3797
  }
3798
+ this.dispatchEvent({
3799
+ type: "user.updated",
3800
+ user: userInfo,
3801
+ me: this.user?.id === userInfo.id ? this.user : void 0
3802
+ });
3643
3803
  }
3644
3804
  };
3645
3805
  this.eventSource.onerror = (event) => {
@@ -3754,6 +3914,17 @@ var ErmisChat = class _ErmisChat {
3754
3914
  this.user.avatar = response.avatar;
3755
3915
  const new_user = { ...this.user, avatar: response.avatar };
3756
3916
  this.state.updateUser(new_user);
3917
+ const userInfo = {
3918
+ id: this.user.id,
3919
+ name: this.user.name ? this.user.name : this.user.id,
3920
+ avatar: this.user?.avatar || ""
3921
+ };
3922
+ this._updateMemberWatcherReferences(userInfo);
3923
+ this._updateUserMessageReferences(userInfo);
3924
+ this.dispatchEvent({
3925
+ type: "user.updated",
3926
+ me: this.user
3927
+ });
3757
3928
  }
3758
3929
  return response;
3759
3930
  }
@@ -3761,6 +3932,19 @@ var ErmisChat = class _ErmisChat {
3761
3932
  let response = await this.patch(this.userBaseURL + "/users/update", updates);
3762
3933
  this.user = response;
3763
3934
  this.state.updateUser(response);
3935
+ if (this.user) {
3936
+ const userInfo = {
3937
+ id: this.user.id,
3938
+ name: this.user.name ? this.user.name : this.user.id,
3939
+ avatar: this.user?.avatar || ""
3940
+ };
3941
+ this._updateMemberWatcherReferences(userInfo);
3942
+ this._updateUserMessageReferences(userInfo);
3943
+ this.dispatchEvent({
3944
+ type: "user.updated",
3945
+ me: this.user
3946
+ });
3947
+ }
3764
3948
  return response;
3765
3949
  }
3766
3950
  /**
@@ -3820,6 +4004,9 @@ var ErmisChat = class _ErmisChat {
3820
4004
  });
3821
4005
  const { channels, userIds } = this.hydrateChannels(data.channels, stateOptions);
3822
4006
  console.log("---channels---", channels);
4007
+ this.dispatchEvent({
4008
+ type: "channels.queried"
4009
+ });
3823
4010
  return channels;
3824
4011
  }
3825
4012
  hydrateChannels(channelsFromApi = [], stateOptions = {}) {
@@ -3975,7 +4162,7 @@ var ErmisChat = class _ErmisChat {
3975
4162
  return pinExpires;
3976
4163
  }
3977
4164
  getUserAgent() {
3978
- return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.8"}`;
4165
+ return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"2.0.0"}`;
3979
4166
  }
3980
4167
  setUserAgent(userAgent) {
3981
4168
  this.userAgent = userAgent;
@@ -4090,1470 +4277,234 @@ var EVENT_MAP = {
4090
4277
  "channel.topic.updated": true
4091
4278
  };
4092
4279
 
4093
- // src/wasm/ermis_call_node_wasm.js
4094
- var wasm;
4095
- var cachedUint8ArrayMemory0 = null;
4096
- function getUint8ArrayMemory0() {
4097
- if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
4098
- cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
4099
- }
4100
- return cachedUint8ArrayMemory0;
4101
- }
4102
- var cachedTextDecoder = new TextDecoder("utf-8", { ignoreBOM: true, fatal: true });
4103
- cachedTextDecoder.decode();
4104
- var MAX_SAFARI_DECODE_BYTES = 2146435072;
4105
- var numBytesDecoded = 0;
4106
- function decodeText(ptr, len) {
4107
- numBytesDecoded += len;
4108
- if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
4109
- cachedTextDecoder = new TextDecoder("utf-8", { ignoreBOM: true, fatal: true });
4110
- cachedTextDecoder.decode();
4111
- numBytesDecoded = len;
4112
- }
4113
- return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
4114
- }
4115
- function getStringFromWasm0(ptr, len) {
4116
- ptr = ptr >>> 0;
4117
- return decodeText(ptr, len);
4118
- }
4119
- var heap = new Array(128).fill(void 0);
4120
- heap.push(void 0, null, true, false);
4121
- var heap_next = heap.length;
4122
- function addHeapObject(obj) {
4123
- if (heap_next === heap.length) heap.push(heap.length + 1);
4124
- const idx = heap_next;
4125
- heap_next = heap[idx];
4126
- heap[idx] = obj;
4127
- return idx;
4128
- }
4129
- function getObject(idx) {
4130
- return heap[idx];
4131
- }
4132
- var WASM_VECTOR_LEN = 0;
4133
- var cachedTextEncoder = new TextEncoder();
4134
- if (!("encodeInto" in cachedTextEncoder)) {
4135
- cachedTextEncoder.encodeInto = function(arg, view) {
4136
- const buf = cachedTextEncoder.encode(arg);
4137
- view.set(buf);
4138
- return {
4139
- read: arg.length,
4140
- written: buf.length
4141
- };
4142
- };
4143
- }
4144
- function passStringToWasm0(arg, malloc, realloc) {
4145
- if (realloc === void 0) {
4146
- const buf = cachedTextEncoder.encode(arg);
4147
- const ptr2 = malloc(buf.length, 1) >>> 0;
4148
- getUint8ArrayMemory0().subarray(ptr2, ptr2 + buf.length).set(buf);
4149
- WASM_VECTOR_LEN = buf.length;
4150
- return ptr2;
4151
- }
4152
- let len = arg.length;
4153
- let ptr = malloc(len, 1) >>> 0;
4154
- const mem = getUint8ArrayMemory0();
4155
- let offset = 0;
4156
- for (; offset < len; offset++) {
4157
- const code = arg.charCodeAt(offset);
4158
- if (code > 127) break;
4159
- mem[ptr + offset] = code;
4160
- }
4161
- if (offset !== len) {
4162
- if (offset !== 0) {
4163
- arg = arg.slice(offset);
4164
- }
4165
- ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
4166
- const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
4167
- const ret = cachedTextEncoder.encodeInto(arg, view);
4168
- offset += ret.written;
4169
- ptr = realloc(ptr, len, offset, 1) >>> 0;
4170
- }
4171
- WASM_VECTOR_LEN = offset;
4172
- return ptr;
4173
- }
4174
- var cachedDataViewMemory0 = null;
4175
- function getDataViewMemory0() {
4176
- if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || cachedDataViewMemory0.buffer.detached === void 0 && cachedDataViewMemory0.buffer !== wasm.memory.buffer) {
4177
- cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
4178
- }
4179
- return cachedDataViewMemory0;
4180
- }
4181
- function isLikeNone(x) {
4182
- return x === void 0 || x === null;
4183
- }
4184
- function debugString(val) {
4185
- const type = typeof val;
4186
- if (type == "number" || type == "boolean" || val == null) {
4187
- return `${val}`;
4188
- }
4189
- if (type == "string") {
4190
- return `"${val}"`;
4191
- }
4192
- if (type == "symbol") {
4193
- const description = val.description;
4194
- if (description == null) {
4195
- return "Symbol";
4196
- } else {
4197
- return `Symbol(${description})`;
4198
- }
4199
- }
4200
- if (type == "function") {
4201
- const name = val.name;
4202
- if (typeof name == "string" && name.length > 0) {
4203
- return `Function(${name})`;
4280
+ // src/wasm_worker_proxy.ts
4281
+ var WasmWorkerProxy = class _WasmWorkerProxy {
4282
+ worker;
4283
+ nextId = 0;
4284
+ pendingCalls = /* @__PURE__ */ new Map();
4285
+ /** Queue cho asyncRecv — Worker gửi data về, Main Thread consume từng cái */
4286
+ recvResolveQueue = [];
4287
+ recvDataQueue = [];
4288
+ recvErrorQueue = [];
4289
+ /** Static cache persist across Worker instances */
4290
+ static cachedBlobUrl = null;
4291
+ static cachedWasmBytes = null;
4292
+ constructor(workerUrl) {
4293
+ if (!_WasmWorkerProxy.cachedBlobUrl) {
4294
+ const url = workerUrl.toString();
4295
+ const xhr = new XMLHttpRequest();
4296
+ xhr.open("GET", url, false);
4297
+ xhr.send();
4298
+ if (xhr.status === 200) {
4299
+ const blob = new Blob([xhr.responseText], { type: "application/javascript" });
4300
+ _WasmWorkerProxy.cachedBlobUrl = URL.createObjectURL(blob);
4301
+ }
4302
+ }
4303
+ if (_WasmWorkerProxy.cachedBlobUrl) {
4304
+ this.worker = new Worker(_WasmWorkerProxy.cachedBlobUrl, { type: "module" });
4204
4305
  } else {
4205
- return "Function";
4306
+ this.worker = new Worker(workerUrl, { type: "module" });
4206
4307
  }
4308
+ this.worker.onmessage = (e) => this.handleMessage(e.data);
4309
+ this.worker.onerror = (e) => {
4310
+ console.error("\u{1F534} WASM Worker error:", e.message);
4311
+ this.pendingCalls.forEach(({ reject }) => reject(new Error(`Worker error: ${e.message}`)));
4312
+ this.pendingCalls.clear();
4313
+ };
4207
4314
  }
4208
- if (Array.isArray(val)) {
4209
- const length = val.length;
4210
- let debug = "[";
4211
- if (length > 0) {
4212
- debug += debugString(val[0]);
4213
- }
4214
- for (let i = 1; i < length; i++) {
4215
- debug += ", " + debugString(val[i]);
4216
- }
4217
- debug += "]";
4218
- return debug;
4219
- }
4220
- const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
4221
- let className;
4222
- if (builtInMatches && builtInMatches.length > 1) {
4223
- className = builtInMatches[1];
4224
- } else {
4225
- return toString.call(val);
4226
- }
4227
- if (className == "Object") {
4228
- try {
4229
- return "Object(" + JSON.stringify(val) + ")";
4230
- } catch (_) {
4231
- return "Object";
4232
- }
4233
- }
4234
- if (val instanceof Error) {
4235
- return `${val.name}: ${val.message}
4236
- ${val.stack}`;
4237
- }
4238
- return className;
4239
- }
4240
- function handleError(f, args) {
4241
- try {
4242
- return f.apply(this, args);
4243
- } catch (e) {
4244
- wasm.__wbindgen_export3(addHeapObject(e));
4315
+ // === LIFECYCLE ===
4316
+ /** Initialize WASM trong Worker — fetch bytes 1 lần, gửi cached bytes cho Worker */
4317
+ async init(wasmPath) {
4318
+ if (!_WasmWorkerProxy.cachedWasmBytes) {
4319
+ const absoluteWasmPath = new URL(
4320
+ wasmPath || "/ermis_call_node_wasm_bg.wasm",
4321
+ window.location.origin
4322
+ ).href;
4323
+ const response = await fetch(absoluteWasmPath);
4324
+ _WasmWorkerProxy.cachedWasmBytes = await response.arrayBuffer();
4325
+ }
4326
+ const bytesCopy = _WasmWorkerProxy.cachedWasmBytes.slice(0);
4327
+ await this.call("init", { wasmBytes: bytesCopy }, [bytesCopy]);
4328
+ }
4329
+ /** Spawn WASM node */
4330
+ async spawn(relayUrls) {
4331
+ await this.call("spawn", { relayUrls });
4332
+ }
4333
+ /** Lấy local endpoint address */
4334
+ async getLocalEndpointAddr() {
4335
+ return await this.call("getLocalEndpointAddr");
4245
4336
  }
4246
- }
4247
- function dropObject(idx) {
4248
- if (idx < 132) return;
4249
- heap[idx] = heap_next;
4250
- heap_next = idx;
4251
- }
4252
- function takeObject(idx) {
4253
- const ret = getObject(idx);
4254
- dropObject(idx);
4255
- return ret;
4256
- }
4257
- function getArrayU8FromWasm0(ptr, len) {
4258
- ptr = ptr >>> 0;
4259
- return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
4260
- }
4261
- var CLOSURE_DTORS = typeof FinalizationRegistry === "undefined" ? { register: () => {
4262
- }, unregister: () => {
4263
- } } : new FinalizationRegistry((state) => state.dtor(state.a, state.b));
4264
- function makeMutClosure(arg0, arg1, dtor, f) {
4265
- const state = { a: arg0, b: arg1, cnt: 1, dtor };
4266
- const real = (...args) => {
4267
- state.cnt++;
4268
- const a = state.a;
4269
- state.a = 0;
4270
- try {
4271
- return f(a, state.b, ...args);
4272
- } finally {
4273
- state.a = a;
4274
- real._wbg_cb_unref();
4275
- }
4276
- };
4277
- real._wbg_cb_unref = () => {
4278
- if (--state.cnt === 0) {
4279
- state.dtor(state.a, state.b);
4280
- state.a = 0;
4281
- CLOSURE_DTORS.unregister(state);
4282
- }
4283
- };
4284
- CLOSURE_DTORS.register(real, state, state);
4285
- return real;
4286
- }
4287
- function makeClosure(arg0, arg1, dtor, f) {
4288
- const state = { a: arg0, b: arg1, cnt: 1, dtor };
4289
- const real = (...args) => {
4290
- state.cnt++;
4291
- try {
4292
- return f(state.a, state.b, ...args);
4293
- } finally {
4294
- real._wbg_cb_unref();
4295
- }
4296
- };
4297
- real._wbg_cb_unref = () => {
4298
- if (--state.cnt === 0) {
4299
- state.dtor(state.a, state.b);
4300
- state.a = 0;
4301
- CLOSURE_DTORS.unregister(state);
4302
- }
4303
- };
4304
- CLOSURE_DTORS.register(real, state, state);
4305
- return real;
4306
- }
4307
- function passArray8ToWasm0(arg, malloc) {
4308
- const ptr = malloc(arg.length * 1, 1) >>> 0;
4309
- getUint8ArrayMemory0().set(arg, ptr / 1);
4310
- WASM_VECTOR_LEN = arg.length;
4311
- return ptr;
4312
- }
4313
- function __wasm_bindgen_func_elem_12858(arg0, arg1) {
4314
- wasm.__wasm_bindgen_func_elem_12858(arg0, arg1);
4315
- }
4316
- function __wasm_bindgen_func_elem_11688(arg0, arg1, arg2) {
4317
- wasm.__wasm_bindgen_func_elem_11688(arg0, arg1, addHeapObject(arg2));
4318
- }
4319
- function __wasm_bindgen_func_elem_6230(arg0, arg1) {
4320
- wasm.__wasm_bindgen_func_elem_6230(arg0, arg1);
4321
- }
4322
- function __wasm_bindgen_func_elem_2287(arg0, arg1, arg2) {
4323
- wasm.__wasm_bindgen_func_elem_2287(arg0, arg1, addHeapObject(arg2));
4324
- }
4325
- function __wasm_bindgen_func_elem_12912(arg0, arg1, arg2) {
4326
- wasm.__wasm_bindgen_func_elem_12912(arg0, arg1, addHeapObject(arg2));
4327
- }
4328
- function __wasm_bindgen_func_elem_5748(arg0, arg1) {
4329
- wasm.__wasm_bindgen_func_elem_5748(arg0, arg1);
4330
- }
4331
- function __wasm_bindgen_func_elem_14376(arg0, arg1, arg2, arg3) {
4332
- wasm.__wasm_bindgen_func_elem_14376(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
4333
- }
4334
- var __wbindgen_enum_BinaryType = ["blob", "arraybuffer"];
4335
- var __wbindgen_enum_ReadableStreamType = ["bytes"];
4336
- var __wbindgen_enum_RequestCache = ["default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached"];
4337
- var __wbindgen_enum_RequestCredentials = ["omit", "same-origin", "include"];
4338
- var __wbindgen_enum_RequestMode = ["same-origin", "no-cors", "cors", "navigate"];
4339
- var ConnectionStatsFinalization = typeof FinalizationRegistry === "undefined" ? { register: () => {
4340
- }, unregister: () => {
4341
- } } : new FinalizationRegistry((ptr) => wasm.__wbg_connectionstats_free(ptr >>> 0, 1));
4342
- var ConnectionStats = class {
4343
- __destroy_into_raw() {
4344
- const ptr = this.__wbg_ptr;
4345
- this.__wbg_ptr = 0;
4346
- ConnectionStatsFinalization.unregister(this);
4347
- return ptr;
4348
- }
4349
- free() {
4350
- const ptr = this.__destroy_into_raw();
4351
- wasm.__wbg_connectionstats_free(ptr, 0);
4337
+ // === INodeCall IMPLEMENTATION ===
4338
+ async connect(address) {
4339
+ await this.call("connect", { address });
4352
4340
  }
4353
- /**
4354
- * @returns {number | undefined}
4355
- */
4356
- get rtt_ms() {
4357
- try {
4358
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4359
- wasm.__wbg_get_connectionstats_rtt_ms(retptr, this.__wbg_ptr);
4360
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4361
- var r2 = getDataViewMemory0().getFloat64(retptr + 8 * 1, true);
4362
- return r0 === 0 ? void 0 : r2;
4363
- } finally {
4364
- wasm.__wbindgen_add_to_stack_pointer(16);
4365
- }
4341
+ async acceptConnection() {
4342
+ await this.call("acceptConnection");
4366
4343
  }
4367
- /**
4368
- * @param {number | null} [arg0]
4369
- */
4370
- set rtt_ms(arg0) {
4371
- wasm.__wbg_set_connectionstats_rtt_ms(this.__wbg_ptr, !isLikeNone(arg0), isLikeNone(arg0) ? 0 : arg0);
4344
+ async sendFrame(data) {
4345
+ await this.call("sendFrame", { data }, [data.buffer]);
4372
4346
  }
4373
- /**
4374
- * @returns {number | undefined}
4375
- */
4376
- get packet_loss() {
4377
- try {
4378
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4379
- wasm.__wbg_get_connectionstats_packet_loss(retptr, this.__wbg_ptr);
4380
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4381
- var r2 = getDataViewMemory0().getFloat64(retptr + 8 * 1, true);
4382
- return r0 === 0 ? void 0 : r2;
4383
- } finally {
4384
- wasm.__wbindgen_add_to_stack_pointer(16);
4385
- }
4347
+ async beginWithGop(data) {
4348
+ await this.call("beginWithGop", { data }, [data.buffer]);
4386
4349
  }
4387
- /**
4388
- * @param {number | null} [arg0]
4389
- */
4390
- set packet_loss(arg0) {
4391
- wasm.__wbg_set_connectionstats_packet_loss(this.__wbg_ptr, !isLikeNone(arg0), isLikeNone(arg0) ? 0 : arg0);
4350
+ async sendAudioFrame(data) {
4351
+ await this.call("sendAudioFrame", { data }, [data.buffer]);
4392
4352
  }
4393
- /**
4394
- * @param {string | null} [connection_type]
4395
- * @param {number | null} [rtt_ms]
4396
- * @param {number | null} [packet_loss]
4397
- */
4398
- constructor(connection_type, rtt_ms, packet_loss) {
4399
- var ptr0 = isLikeNone(connection_type) ? 0 : passStringToWasm0(connection_type, wasm.__wbindgen_export, wasm.__wbindgen_export2);
4400
- var len0 = WASM_VECTOR_LEN;
4401
- const ret = wasm.connectionstats_new(ptr0, len0, !isLikeNone(rtt_ms), isLikeNone(rtt_ms) ? 0 : rtt_ms, !isLikeNone(packet_loss), isLikeNone(packet_loss) ? 0 : packet_loss);
4402
- this.__wbg_ptr = ret >>> 0;
4403
- ConnectionStatsFinalization.register(this, this.__wbg_ptr, this);
4404
- return this;
4353
+ async sendControlFrame(data) {
4354
+ await this.call("sendControlFrame", { data });
4405
4355
  }
4406
4356
  /**
4407
- * @returns {string | undefined}
4357
+ * asyncRecv nhận data từ Worker recv loop.
4358
+ *
4359
+ * Worker chạy recv loop nội bộ, gửi data về qua postMessage.
4360
+ * Method này trả về Promise resolve khi có data mới.
4361
+ * KHÔNG BAO GIỜ block Main Thread — chỉ chờ postMessage event.
4408
4362
  */
4409
- get connection_type() {
4410
- try {
4411
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4412
- wasm.connectionstats_connection_type(retptr, this.__wbg_ptr);
4413
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4414
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
4415
- let v1;
4416
- if (r0 !== 0) {
4417
- v1 = getStringFromWasm0(r0, r1).slice();
4418
- wasm.__wbindgen_export4(r0, r1 * 1, 1);
4419
- }
4420
- return v1;
4421
- } finally {
4422
- wasm.__wbindgen_add_to_stack_pointer(16);
4363
+ async asyncRecv() {
4364
+ if (this.recvDataQueue.length > 0) {
4365
+ return this.recvDataQueue.shift();
4423
4366
  }
4367
+ return new Promise((resolve, reject) => {
4368
+ this.recvResolveQueue.push(resolve);
4369
+ this.recvErrorQueue.push(reject);
4370
+ });
4424
4371
  }
4425
- /**
4426
- * @param {string | null} [value]
4427
- */
4428
- set connection_type(value) {
4429
- var ptr0 = isLikeNone(value) ? 0 : passStringToWasm0(value, wasm.__wbindgen_export, wasm.__wbindgen_export2);
4430
- var len0 = WASM_VECTOR_LEN;
4431
- wasm.connectionstats_set_connection_type(this.__wbg_ptr, ptr0, len0);
4432
- }
4433
- };
4434
- if (Symbol.dispose) ConnectionStats.prototype[Symbol.dispose] = ConnectionStats.prototype.free;
4435
- var ErmisCallFinalization = typeof FinalizationRegistry === "undefined" ? { register: () => {
4436
- }, unregister: () => {
4437
- } } : new FinalizationRegistry((ptr) => wasm.__wbg_ermiscall_free(ptr >>> 0, 1));
4438
- var ErmisCall = class {
4439
- __destroy_into_raw() {
4440
- const ptr = this.__wbg_ptr;
4441
- this.__wbg_ptr = 0;
4442
- ErmisCallFinalization.unregister(this);
4443
- return ptr;
4444
- }
4445
- free() {
4446
- const ptr = this.__destroy_into_raw();
4447
- wasm.__wbg_ermiscall_free(ptr, 0);
4372
+ // === CONTROL ===
4373
+ /** Bắt đầu recv loop trong Worker */
4374
+ async startRecvLoop() {
4375
+ await this.call("startRecvLoop");
4448
4376
  }
4449
- constructor() {
4450
- const ret = wasm.ermiscall_new();
4451
- this.__wbg_ptr = ret >>> 0;
4452
- ErmisCallFinalization.register(this, this.__wbg_ptr, this);
4453
- return this;
4377
+ /** Dừng recv loop trong Worker */
4378
+ async stopRecvLoop() {
4379
+ await this.call("stopRecvLoop");
4454
4380
  }
4455
- /**
4456
- * @param {any} relay_urls
4457
- * @param {Uint8Array | null} [secret_key]
4458
- * @returns {Promise<void>}
4459
- */
4460
- spawn(relay_urls, secret_key) {
4461
- var ptr0 = isLikeNone(secret_key) ? 0 : passArray8ToWasm0(secret_key, wasm.__wbindgen_export);
4462
- var len0 = WASM_VECTOR_LEN;
4463
- const ret = wasm.ermiscall_spawn(this.__wbg_ptr, addHeapObject(relay_urls), ptr0, len0);
4464
- return takeObject(ret);
4381
+ async closeEndpoint() {
4382
+ await this.call("closeEndpoint");
4465
4383
  }
4466
- /**
4467
- * @returns {Promise<string>}
4468
- */
4469
- getLocalEndpointAddr() {
4470
- const ret = wasm.ermiscall_getLocalEndpointAddr(this.__wbg_ptr);
4471
- return takeObject(ret);
4384
+ closeConnection() {
4385
+ const id = this.nextId++;
4386
+ this.worker.postMessage({ id, type: "closeConnection" });
4472
4387
  }
4473
- /**
4474
- * @param {string} addr
4475
- * @returns {Promise<void>}
4476
- */
4477
- connect(addr) {
4478
- const ptr0 = passStringToWasm0(addr, wasm.__wbindgen_export, wasm.__wbindgen_export2);
4479
- const len0 = WASM_VECTOR_LEN;
4480
- const ret = wasm.ermiscall_connect(this.__wbg_ptr, ptr0, len0);
4481
- return takeObject(ret);
4388
+ networkChange() {
4389
+ const id = this.nextId++;
4390
+ this.worker.postMessage({ id, type: "networkChange" });
4482
4391
  }
4483
- /**
4484
- * @returns {Promise<void>}
4485
- */
4486
- closeEndpoint() {
4487
- const ret = wasm.ermiscall_closeEndpoint(this.__wbg_ptr);
4488
- return takeObject(ret);
4392
+ async getStats() {
4393
+ return await this.call("getStats");
4489
4394
  }
4490
- closeConnection() {
4395
+ /** Terminate Worker — gọi khi call kết thúc */
4396
+ async terminate() {
4491
4397
  try {
4492
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4493
- wasm.ermiscall_closeConnection(retptr, this.__wbg_ptr);
4494
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4495
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
4496
- if (r1) {
4497
- throw takeObject(r0);
4398
+ await this.call("terminate");
4399
+ } catch {
4400
+ }
4401
+ this.worker.terminate();
4402
+ this.recvResolveQueue = [];
4403
+ this.recvErrorQueue.forEach((reject) => reject(new Error("Worker terminated")));
4404
+ this.recvErrorQueue = [];
4405
+ this.recvDataQueue = [];
4406
+ }
4407
+ // === INTERNAL ===
4408
+ handleMessage(msg) {
4409
+ if (msg.type === "recv_data") {
4410
+ const data = msg.data;
4411
+ if (this.recvResolveQueue.length > 0) {
4412
+ const resolve = this.recvResolveQueue.shift();
4413
+ this.recvErrorQueue.shift();
4414
+ resolve(data);
4415
+ } else {
4416
+ this.recvDataQueue.push(data);
4498
4417
  }
4499
- } finally {
4500
- wasm.__wbindgen_add_to_stack_pointer(16);
4418
+ return;
4501
4419
  }
4502
- }
4503
- /**
4504
- * @returns {Promise<void>}
4505
- */
4506
- acceptConnection() {
4507
- const ret = wasm.ermiscall_acceptConnection(this.__wbg_ptr);
4508
- return takeObject(ret);
4509
- }
4510
- /**
4511
- * @param {Uint8Array} data
4512
- */
4513
- sendControlFrame(data) {
4514
- try {
4515
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4516
- const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_export);
4517
- const len0 = WASM_VECTOR_LEN;
4518
- wasm.ermiscall_sendControlFrame(retptr, this.__wbg_ptr, ptr0, len0);
4519
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4520
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
4521
- if (r1) {
4522
- throw takeObject(r0);
4420
+ if (msg.type === "recv_error") {
4421
+ const error = new Error(msg.error);
4422
+ if (this.recvErrorQueue.length > 0) {
4423
+ const reject = this.recvErrorQueue.shift();
4424
+ this.recvResolveQueue.shift();
4425
+ reject(error);
4523
4426
  }
4524
- } finally {
4525
- wasm.__wbindgen_add_to_stack_pointer(16);
4427
+ return;
4428
+ }
4429
+ const { id } = msg;
4430
+ const pending = this.pendingCalls.get(id);
4431
+ if (!pending) return;
4432
+ this.pendingCalls.delete(id);
4433
+ if (msg.type === "error") {
4434
+ pending.reject(new Error(msg.error));
4435
+ } else {
4436
+ pending.resolve(msg.data);
4526
4437
  }
4527
4438
  }
4528
- /**
4529
- * @param {Uint8Array} data
4530
- */
4531
- sendAudioFrame(data) {
4532
- try {
4533
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4534
- const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_export);
4535
- const len0 = WASM_VECTOR_LEN;
4536
- wasm.ermiscall_sendAudioFrame(retptr, this.__wbg_ptr, ptr0, len0);
4537
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4538
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
4539
- if (r1) {
4540
- throw takeObject(r0);
4439
+ /** Send RPC call to Worker and wait for response */
4440
+ call(type, payload, transfer) {
4441
+ const id = this.nextId++;
4442
+ return new Promise((resolve, reject) => {
4443
+ this.pendingCalls.set(id, { resolve, reject });
4444
+ const message = { id, type, ...payload };
4445
+ if (transfer && transfer.length > 0) {
4446
+ this.worker.postMessage(message, transfer);
4447
+ } else {
4448
+ this.worker.postMessage(message);
4541
4449
  }
4542
- } finally {
4543
- wasm.__wbindgen_add_to_stack_pointer(16);
4544
- }
4450
+ });
4451
+ }
4452
+ };
4453
+
4454
+ // src/media_stream_sender.ts
4455
+ var MediaStreamSender = class {
4456
+ videoEncoder = null;
4457
+ audioEncoder = null;
4458
+ videoReader = null;
4459
+ audioReader = null;
4460
+ localStream = null;
4461
+ videoConfig = null;
4462
+ audioConfig = null;
4463
+ videoConfigSent = false;
4464
+ audioConfigSent = false;
4465
+ hasVideo = false;
4466
+ hasAudio = false;
4467
+ forceKeyFrame = false;
4468
+ isSendingVideo = false;
4469
+ isSendingAudio = false;
4470
+ nodeCall;
4471
+ healthCallInterval = null;
4472
+ constructor(nodeCall) {
4473
+ this.nodeCall = nodeCall;
4545
4474
  }
4546
4475
  /**
4547
- * @param {Uint8Array} data
4476
+ * Bắt đầu xử lý MediaStream
4548
4477
  */
4549
- sendFrame(data) {
4478
+ async connect(address) {
4550
4479
  try {
4551
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4552
- const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_export);
4553
- const len0 = WASM_VECTOR_LEN;
4554
- wasm.ermiscall_sendFrame(retptr, this.__wbg_ptr, ptr0, len0);
4555
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4556
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
4557
- if (r1) {
4558
- throw takeObject(r0);
4559
- }
4560
- } finally {
4561
- wasm.__wbindgen_add_to_stack_pointer(16);
4480
+ await this.nodeCall.connect(address);
4481
+ await this.sendConnected();
4482
+ await this.sendConfigs();
4483
+ this.startHealthCallInterval();
4484
+ } catch (error) {
4485
+ console.error("Error starting MediaStreamSender:", error);
4562
4486
  }
4563
4487
  }
4564
- notifyNewGop() {
4488
+ async sendConfigs() {
4565
4489
  try {
4566
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4567
- wasm.ermiscall_notifyNewGop(retptr, this.__wbg_ptr);
4568
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4569
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
4570
- if (r1) {
4571
- throw takeObject(r0);
4490
+ await this.sendTransceiverState(this.hasAudio, this.hasVideo);
4491
+ await this.sendAudioConfig();
4492
+ const videoTrack = this.localStream?.getVideoTracks()[0];
4493
+ if (videoTrack) {
4494
+ await this.sendVideoConfig();
4572
4495
  }
4573
- } finally {
4574
- wasm.__wbindgen_add_to_stack_pointer(16);
4496
+ } catch (error) {
4497
+ console.error("Error sending configs:", error);
4575
4498
  }
4576
4499
  }
4577
4500
  /**
4578
- * @returns {Uint8Array}
4501
+ * Dừng và reset encoders
4579
4502
  */
4580
- recv() {
4581
- try {
4582
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4583
- wasm.ermiscall_recv(retptr, this.__wbg_ptr);
4584
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4585
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
4586
- var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
4587
- if (r2) {
4588
- throw takeObject(r1);
4589
- }
4590
- return takeObject(r0);
4591
- } finally {
4592
- wasm.__wbindgen_add_to_stack_pointer(16);
4503
+ stop = () => {
4504
+ if (this.healthCallInterval) {
4505
+ clearInterval(this.healthCallInterval);
4506
+ this.healthCallInterval = null;
4593
4507
  }
4594
- }
4595
- /**
4596
- * @returns {Promise<Uint8Array>}
4597
- */
4598
- asyncRecv() {
4599
- const ret = wasm.ermiscall_asyncRecv(this.__wbg_ptr);
4600
- return takeObject(ret);
4601
- }
4602
- /**
4603
- * @param {Uint8Array} data
4604
- */
4605
- beginWithGop(data) {
4606
- try {
4607
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4608
- const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_export);
4609
- const len0 = WASM_VECTOR_LEN;
4610
- wasm.ermiscall_beginWithGop(retptr, this.__wbg_ptr, ptr0, len0);
4611
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4612
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
4613
- if (r1) {
4614
- throw takeObject(r0);
4615
- }
4616
- } finally {
4617
- wasm.__wbindgen_add_to_stack_pointer(16);
4618
- }
4619
- }
4620
- /**
4621
- * @returns {string | undefined}
4622
- */
4623
- connectionType() {
4624
- try {
4625
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4626
- wasm.ermiscall_connectionType(retptr, this.__wbg_ptr);
4627
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4628
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
4629
- let v1;
4630
- if (r0 !== 0) {
4631
- v1 = getStringFromWasm0(r0, r1).slice();
4632
- wasm.__wbindgen_export4(r0, r1 * 1, 1);
4633
- }
4634
- return v1;
4635
- } finally {
4636
- wasm.__wbindgen_add_to_stack_pointer(16);
4637
- }
4638
- }
4639
- /**
4640
- * @returns {number | undefined}
4641
- */
4642
- roundTripTime() {
4643
- try {
4644
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4645
- wasm.ermiscall_roundTripTime(retptr, this.__wbg_ptr);
4646
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4647
- var r2 = getDataViewMemory0().getFloat64(retptr + 8 * 1, true);
4648
- return r0 === 0 ? void 0 : r2;
4649
- } finally {
4650
- wasm.__wbindgen_add_to_stack_pointer(16);
4651
- }
4652
- }
4653
- /**
4654
- * @returns {number | undefined}
4655
- */
4656
- currentPacketLoss() {
4657
- try {
4658
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4659
- wasm.ermiscall_currentPacketLoss(retptr, this.__wbg_ptr);
4660
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4661
- var r2 = getDataViewMemory0().getFloat64(retptr + 8 * 1, true);
4662
- return r0 === 0 ? void 0 : r2;
4663
- } finally {
4664
- wasm.__wbindgen_add_to_stack_pointer(16);
4665
- }
4666
- }
4667
- networkChange() {
4668
- wasm.ermiscall_networkChange(this.__wbg_ptr);
4669
- }
4670
- /**
4671
- * @returns {any}
4672
- */
4673
- getStats() {
4674
- try {
4675
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
4676
- wasm.ermiscall_getStats(retptr, this.__wbg_ptr);
4677
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
4678
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
4679
- var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
4680
- if (r2) {
4681
- throw takeObject(r1);
4682
- }
4683
- return takeObject(r0);
4684
- } finally {
4685
- wasm.__wbindgen_add_to_stack_pointer(16);
4686
- }
4687
- }
4688
- };
4689
- if (Symbol.dispose) ErmisCall.prototype[Symbol.dispose] = ErmisCall.prototype.free;
4690
- var IntoUnderlyingByteSourceFinalization = typeof FinalizationRegistry === "undefined" ? { register: () => {
4691
- }, unregister: () => {
4692
- } } : new FinalizationRegistry((ptr) => wasm.__wbg_intounderlyingbytesource_free(ptr >>> 0, 1));
4693
- var IntoUnderlyingByteSource = class {
4694
- __destroy_into_raw() {
4695
- const ptr = this.__wbg_ptr;
4696
- this.__wbg_ptr = 0;
4697
- IntoUnderlyingByteSourceFinalization.unregister(this);
4698
- return ptr;
4699
- }
4700
- free() {
4701
- const ptr = this.__destroy_into_raw();
4702
- wasm.__wbg_intounderlyingbytesource_free(ptr, 0);
4703
- }
4704
- /**
4705
- * @returns {ReadableStreamType}
4706
- */
4707
- get type() {
4708
- const ret = wasm.intounderlyingbytesource_type(this.__wbg_ptr);
4709
- return __wbindgen_enum_ReadableStreamType[ret];
4710
- }
4711
- /**
4712
- * @returns {number}
4713
- */
4714
- get autoAllocateChunkSize() {
4715
- const ret = wasm.intounderlyingbytesource_autoAllocateChunkSize(this.__wbg_ptr);
4716
- return ret >>> 0;
4717
- }
4718
- /**
4719
- * @param {ReadableByteStreamController} controller
4720
- */
4721
- start(controller) {
4722
- wasm.intounderlyingbytesource_start(this.__wbg_ptr, addHeapObject(controller));
4723
- }
4724
- /**
4725
- * @param {ReadableByteStreamController} controller
4726
- * @returns {Promise<any>}
4727
- */
4728
- pull(controller) {
4729
- const ret = wasm.intounderlyingbytesource_pull(this.__wbg_ptr, addHeapObject(controller));
4730
- return takeObject(ret);
4731
- }
4732
- cancel() {
4733
- const ptr = this.__destroy_into_raw();
4734
- wasm.intounderlyingbytesource_cancel(ptr);
4735
- }
4736
- };
4737
- if (Symbol.dispose) IntoUnderlyingByteSource.prototype[Symbol.dispose] = IntoUnderlyingByteSource.prototype.free;
4738
- var IntoUnderlyingSinkFinalization = typeof FinalizationRegistry === "undefined" ? { register: () => {
4739
- }, unregister: () => {
4740
- } } : new FinalizationRegistry((ptr) => wasm.__wbg_intounderlyingsink_free(ptr >>> 0, 1));
4741
- var IntoUnderlyingSink = class {
4742
- __destroy_into_raw() {
4743
- const ptr = this.__wbg_ptr;
4744
- this.__wbg_ptr = 0;
4745
- IntoUnderlyingSinkFinalization.unregister(this);
4746
- return ptr;
4747
- }
4748
- free() {
4749
- const ptr = this.__destroy_into_raw();
4750
- wasm.__wbg_intounderlyingsink_free(ptr, 0);
4751
- }
4752
- /**
4753
- * @param {any} chunk
4754
- * @returns {Promise<any>}
4755
- */
4756
- write(chunk) {
4757
- const ret = wasm.intounderlyingsink_write(this.__wbg_ptr, addHeapObject(chunk));
4758
- return takeObject(ret);
4759
- }
4760
- /**
4761
- * @returns {Promise<any>}
4762
- */
4763
- close() {
4764
- const ptr = this.__destroy_into_raw();
4765
- const ret = wasm.intounderlyingsink_close(ptr);
4766
- return takeObject(ret);
4767
- }
4768
- /**
4769
- * @param {any} reason
4770
- * @returns {Promise<any>}
4771
- */
4772
- abort(reason) {
4773
- const ptr = this.__destroy_into_raw();
4774
- const ret = wasm.intounderlyingsink_abort(ptr, addHeapObject(reason));
4775
- return takeObject(ret);
4776
- }
4777
- };
4778
- if (Symbol.dispose) IntoUnderlyingSink.prototype[Symbol.dispose] = IntoUnderlyingSink.prototype.free;
4779
- var IntoUnderlyingSourceFinalization = typeof FinalizationRegistry === "undefined" ? { register: () => {
4780
- }, unregister: () => {
4781
- } } : new FinalizationRegistry((ptr) => wasm.__wbg_intounderlyingsource_free(ptr >>> 0, 1));
4782
- var IntoUnderlyingSource = class {
4783
- __destroy_into_raw() {
4784
- const ptr = this.__wbg_ptr;
4785
- this.__wbg_ptr = 0;
4786
- IntoUnderlyingSourceFinalization.unregister(this);
4787
- return ptr;
4788
- }
4789
- free() {
4790
- const ptr = this.__destroy_into_raw();
4791
- wasm.__wbg_intounderlyingsource_free(ptr, 0);
4792
- }
4793
- /**
4794
- * @param {ReadableStreamDefaultController} controller
4795
- * @returns {Promise<any>}
4796
- */
4797
- pull(controller) {
4798
- const ret = wasm.intounderlyingsource_pull(this.__wbg_ptr, addHeapObject(controller));
4799
- return takeObject(ret);
4800
- }
4801
- cancel() {
4802
- const ptr = this.__destroy_into_raw();
4803
- wasm.intounderlyingsource_cancel(ptr);
4804
- }
4805
- };
4806
- if (Symbol.dispose) IntoUnderlyingSource.prototype[Symbol.dispose] = IntoUnderlyingSource.prototype.free;
4807
- var EXPECTED_RESPONSE_TYPES = /* @__PURE__ */ new Set(["basic", "cors", "default"]);
4808
- async function __wbg_load(module2, imports) {
4809
- if (typeof Response === "function" && module2 instanceof Response) {
4810
- if (typeof WebAssembly.instantiateStreaming === "function") {
4811
- try {
4812
- return await WebAssembly.instantiateStreaming(module2, imports);
4813
- } catch (e) {
4814
- const validResponse = module2.ok && EXPECTED_RESPONSE_TYPES.has(module2.type);
4815
- if (validResponse && module2.headers.get("Content-Type") !== "application/wasm") {
4816
- console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
4817
- } else {
4818
- throw e;
4819
- }
4820
- }
4821
- }
4822
- const bytes = await module2.arrayBuffer();
4823
- return await WebAssembly.instantiate(bytes, imports);
4824
- } else {
4825
- const instance = await WebAssembly.instantiate(module2, imports);
4826
- if (instance instanceof WebAssembly.Instance) {
4827
- return { instance, module: module2 };
4828
- } else {
4829
- return instance;
4830
- }
4831
- }
4832
- }
4833
- function __wbg_get_imports() {
4834
- const imports = {};
4835
- imports.wbg = {};
4836
- imports.wbg.__wbg_Error_e83987f665cf5504 = function(arg0, arg1) {
4837
- const ret = Error(getStringFromWasm0(arg0, arg1));
4838
- return addHeapObject(ret);
4839
- };
4840
- imports.wbg.__wbg_String_8f0eb39a4a4c2f66 = function(arg0, arg1) {
4841
- const ret = String(getObject(arg1));
4842
- const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
4843
- const len1 = WASM_VECTOR_LEN;
4844
- getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
4845
- getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
4846
- };
4847
- imports.wbg.__wbg___wbindgen_boolean_get_6d5a1ee65bab5f68 = function(arg0) {
4848
- const v = getObject(arg0);
4849
- const ret = typeof v === "boolean" ? v : void 0;
4850
- return isLikeNone(ret) ? 16777215 : ret ? 1 : 0;
4851
- };
4852
- imports.wbg.__wbg___wbindgen_debug_string_df47ffb5e35e6763 = function(arg0, arg1) {
4853
- const ret = debugString(getObject(arg1));
4854
- const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
4855
- const len1 = WASM_VECTOR_LEN;
4856
- getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
4857
- getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
4858
- };
4859
- imports.wbg.__wbg___wbindgen_is_function_ee8a6c5833c90377 = function(arg0) {
4860
- const ret = typeof getObject(arg0) === "function";
4861
- return ret;
4862
- };
4863
- imports.wbg.__wbg___wbindgen_is_object_c818261d21f283a4 = function(arg0) {
4864
- const val = getObject(arg0);
4865
- const ret = typeof val === "object" && val !== null;
4866
- return ret;
4867
- };
4868
- imports.wbg.__wbg___wbindgen_is_string_fbb76cb2940daafd = function(arg0) {
4869
- const ret = typeof getObject(arg0) === "string";
4870
- return ret;
4871
- };
4872
- imports.wbg.__wbg___wbindgen_is_undefined_2d472862bd29a478 = function(arg0) {
4873
- const ret = getObject(arg0) === void 0;
4874
- return ret;
4875
- };
4876
- imports.wbg.__wbg___wbindgen_jsval_loose_eq_b664b38a2f582147 = function(arg0, arg1) {
4877
- const ret = getObject(arg0) == getObject(arg1);
4878
- return ret;
4879
- };
4880
- imports.wbg.__wbg___wbindgen_number_get_a20bf9b85341449d = function(arg0, arg1) {
4881
- const obj = getObject(arg1);
4882
- const ret = typeof obj === "number" ? obj : void 0;
4883
- getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
4884
- getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
4885
- };
4886
- imports.wbg.__wbg___wbindgen_string_get_e4f06c90489ad01b = function(arg0, arg1) {
4887
- const obj = getObject(arg1);
4888
- const ret = typeof obj === "string" ? obj : void 0;
4889
- var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
4890
- var len1 = WASM_VECTOR_LEN;
4891
- getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
4892
- getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
4893
- };
4894
- imports.wbg.__wbg___wbindgen_throw_b855445ff6a94295 = function(arg0, arg1) {
4895
- throw new Error(getStringFromWasm0(arg0, arg1));
4896
- };
4897
- imports.wbg.__wbg__wbg_cb_unref_2454a539ea5790d9 = function(arg0) {
4898
- getObject(arg0)._wbg_cb_unref();
4899
- };
4900
- imports.wbg.__wbg_abort_28ad55c5825b004d = function(arg0, arg1) {
4901
- getObject(arg0).abort(getObject(arg1));
4902
- };
4903
- imports.wbg.__wbg_abort_e7eb059f72f9ed0c = function(arg0) {
4904
- getObject(arg0).abort();
4905
- };
4906
- imports.wbg.__wbg_addEventListener_40dc0fc428fc49e1 = function() {
4907
- return handleError(function(arg0, arg1, arg2, arg3) {
4908
- getObject(arg0).addEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3));
4909
- }, arguments);
4910
- };
4911
- imports.wbg.__wbg_append_b577eb3a177bc0fa = function() {
4912
- return handleError(function(arg0, arg1, arg2, arg3, arg4) {
4913
- getObject(arg0).append(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
4914
- }, arguments);
4915
- };
4916
- imports.wbg.__wbg_body_587542b2fd8e06c0 = function(arg0) {
4917
- const ret = getObject(arg0).body;
4918
- return isLikeNone(ret) ? 0 : addHeapObject(ret);
4919
- };
4920
- imports.wbg.__wbg_buffer_ccc4520b36d3ccf4 = function(arg0) {
4921
- const ret = getObject(arg0).buffer;
4922
- return addHeapObject(ret);
4923
- };
4924
- imports.wbg.__wbg_byobRequest_2344e6975f27456e = function(arg0) {
4925
- const ret = getObject(arg0).byobRequest;
4926
- return isLikeNone(ret) ? 0 : addHeapObject(ret);
4927
- };
4928
- imports.wbg.__wbg_byteLength_bcd42e4025299788 = function(arg0) {
4929
- const ret = getObject(arg0).byteLength;
4930
- return ret;
4931
- };
4932
- imports.wbg.__wbg_byteOffset_ca3a6cf7944b364b = function(arg0) {
4933
- const ret = getObject(arg0).byteOffset;
4934
- return ret;
4935
- };
4936
- imports.wbg.__wbg_call_525440f72fbfc0ea = function() {
4937
- return handleError(function(arg0, arg1, arg2) {
4938
- const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
4939
- return addHeapObject(ret);
4940
- }, arguments);
4941
- };
4942
- imports.wbg.__wbg_call_e762c39fa8ea36bf = function() {
4943
- return handleError(function(arg0, arg1) {
4944
- const ret = getObject(arg0).call(getObject(arg1));
4945
- return addHeapObject(ret);
4946
- }, arguments);
4947
- };
4948
- imports.wbg.__wbg_cancel_48ab6f9dc366e369 = function(arg0) {
4949
- const ret = getObject(arg0).cancel();
4950
- return addHeapObject(ret);
4951
- };
4952
- imports.wbg.__wbg_catch_943836faa5d29bfb = function(arg0, arg1) {
4953
- const ret = getObject(arg0).catch(getObject(arg1));
4954
- return addHeapObject(ret);
4955
- };
4956
- imports.wbg.__wbg_clearTimeout_15dfc3d1dcb635c6 = function() {
4957
- return handleError(function(arg0, arg1) {
4958
- getObject(arg0).clearTimeout(takeObject(arg1));
4959
- }, arguments);
4960
- };
4961
- imports.wbg.__wbg_clearTimeout_7a42b49784aea641 = function(arg0) {
4962
- const ret = clearTimeout(takeObject(arg0));
4963
- return addHeapObject(ret);
4964
- };
4965
- imports.wbg.__wbg_close_5a6caed3231b68cd = function() {
4966
- return handleError(function(arg0) {
4967
- getObject(arg0).close();
4968
- }, arguments);
4969
- };
4970
- imports.wbg.__wbg_close_6956df845478561a = function() {
4971
- return handleError(function(arg0) {
4972
- getObject(arg0).close();
4973
- }, arguments);
4974
- };
4975
- imports.wbg.__wbg_close_885e277edf06b3fa = function() {
4976
- return handleError(function(arg0) {
4977
- getObject(arg0).close();
4978
- }, arguments);
4979
- };
4980
- imports.wbg.__wbg_code_20d453b11b200026 = function(arg0) {
4981
- const ret = getObject(arg0).code;
4982
- return ret;
4983
- };
4984
- imports.wbg.__wbg_code_218f5fdf8c7fcabd = function(arg0) {
4985
- const ret = getObject(arg0).code;
4986
- return ret;
4987
- };
4988
- imports.wbg.__wbg_crypto_574e78ad8b13b65f = function(arg0) {
4989
- const ret = getObject(arg0).crypto;
4990
- return addHeapObject(ret);
4991
- };
4992
- imports.wbg.__wbg_data_ee4306d069f24f2d = function(arg0) {
4993
- const ret = getObject(arg0).data;
4994
- return addHeapObject(ret);
4995
- };
4996
- imports.wbg.__wbg_done_2042aa2670fb1db1 = function(arg0) {
4997
- const ret = getObject(arg0).done;
4998
- return ret;
4999
- };
5000
- imports.wbg.__wbg_enqueue_7b18a650aec77898 = function() {
5001
- return handleError(function(arg0, arg1) {
5002
- getObject(arg0).enqueue(getObject(arg1));
5003
- }, arguments);
5004
- };
5005
- imports.wbg.__wbg_fetch_74a3e84ebd2c9a0e = function(arg0) {
5006
- const ret = fetch(getObject(arg0));
5007
- return addHeapObject(ret);
5008
- };
5009
- imports.wbg.__wbg_fetch_f8ba0e29a9d6de0d = function(arg0, arg1) {
5010
- const ret = getObject(arg0).fetch(getObject(arg1));
5011
- return addHeapObject(ret);
5012
- };
5013
- imports.wbg.__wbg_getRandomValues_1c61fac11405ffdc = function() {
5014
- return handleError(function(arg0, arg1) {
5015
- globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1));
5016
- }, arguments);
5017
- };
5018
- imports.wbg.__wbg_getRandomValues_b8f5dbd5f3995a9e = function() {
5019
- return handleError(function(arg0, arg1) {
5020
- getObject(arg0).getRandomValues(getObject(arg1));
5021
- }, arguments);
5022
- };
5023
- imports.wbg.__wbg_getReader_48e00749fe3f6089 = function() {
5024
- return handleError(function(arg0) {
5025
- const ret = getObject(arg0).getReader();
5026
- return addHeapObject(ret);
5027
- }, arguments);
5028
- };
5029
- imports.wbg.__wbg_getTime_14776bfb48a1bff9 = function(arg0) {
5030
- const ret = getObject(arg0).getTime();
5031
- return ret;
5032
- };
5033
- imports.wbg.__wbg_get_7bed016f185add81 = function(arg0, arg1) {
5034
- const ret = getObject(arg0)[arg1 >>> 0];
5035
- return addHeapObject(ret);
5036
- };
5037
- imports.wbg.__wbg_get_done_a0463af43a1fc764 = function(arg0) {
5038
- const ret = getObject(arg0).done;
5039
- return isLikeNone(ret) ? 16777215 : ret ? 1 : 0;
5040
- };
5041
- imports.wbg.__wbg_get_efcb449f58ec27c2 = function() {
5042
- return handleError(function(arg0, arg1) {
5043
- const ret = Reflect.get(getObject(arg0), getObject(arg1));
5044
- return addHeapObject(ret);
5045
- }, arguments);
5046
- };
5047
- imports.wbg.__wbg_get_value_5ce96c9f81ce7398 = function(arg0) {
5048
- const ret = getObject(arg0).value;
5049
- return addHeapObject(ret);
5050
- };
5051
- imports.wbg.__wbg_has_787fafc980c3ccdb = function() {
5052
- return handleError(function(arg0, arg1) {
5053
- const ret = Reflect.has(getObject(arg0), getObject(arg1));
5054
- return ret;
5055
- }, arguments);
5056
- };
5057
- imports.wbg.__wbg_headers_b87d7eaba61c3278 = function(arg0) {
5058
- const ret = getObject(arg0).headers;
5059
- return addHeapObject(ret);
5060
- };
5061
- imports.wbg.__wbg_instanceof_ArrayBuffer_70beb1189ca63b38 = function(arg0) {
5062
- let result;
5063
- try {
5064
- result = getObject(arg0) instanceof ArrayBuffer;
5065
- } catch (_) {
5066
- result = false;
5067
- }
5068
- const ret = result;
5069
- return ret;
5070
- };
5071
- imports.wbg.__wbg_instanceof_Blob_23b3322f66e5a83b = function(arg0) {
5072
- let result;
5073
- try {
5074
- result = getObject(arg0) instanceof Blob;
5075
- } catch (_) {
5076
- result = false;
5077
- }
5078
- const ret = result;
5079
- return ret;
5080
- };
5081
- imports.wbg.__wbg_instanceof_Response_f4f3e87e07f3135c = function(arg0) {
5082
- let result;
5083
- try {
5084
- result = getObject(arg0) instanceof Response;
5085
- } catch (_) {
5086
- result = false;
5087
- }
5088
- const ret = result;
5089
- return ret;
5090
- };
5091
- imports.wbg.__wbg_instanceof_Uint8Array_20c8e73002f7af98 = function(arg0) {
5092
- let result;
5093
- try {
5094
- result = getObject(arg0) instanceof Uint8Array;
5095
- } catch (_) {
5096
- result = false;
5097
- }
5098
- const ret = result;
5099
- return ret;
5100
- };
5101
- imports.wbg.__wbg_isArray_96e0af9891d0945d = function(arg0) {
5102
- const ret = Array.isArray(getObject(arg0));
5103
- return ret;
5104
- };
5105
- imports.wbg.__wbg_iterator_e5822695327a3c39 = function() {
5106
- const ret = Symbol.iterator;
5107
- return addHeapObject(ret);
5108
- };
5109
- imports.wbg.__wbg_length_69bca3cb64fc8748 = function(arg0) {
5110
- const ret = getObject(arg0).length;
5111
- return ret;
5112
- };
5113
- imports.wbg.__wbg_length_cdd215e10d9dd507 = function(arg0) {
5114
- const ret = getObject(arg0).length;
5115
- return ret;
5116
- };
5117
- imports.wbg.__wbg_log_ee0138cca4957740 = function(arg0, arg1) {
5118
- console.log(getStringFromWasm0(arg0, arg1));
5119
- };
5120
- imports.wbg.__wbg_message_bd42dbe3f2f3ed8e = function(arg0, arg1) {
5121
- const ret = getObject(arg1).message;
5122
- const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
5123
- const len1 = WASM_VECTOR_LEN;
5124
- getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
5125
- getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
5126
- };
5127
- imports.wbg.__wbg_msCrypto_a61aeb35a24c1329 = function(arg0) {
5128
- const ret = getObject(arg0).msCrypto;
5129
- return addHeapObject(ret);
5130
- };
5131
- imports.wbg.__wbg_new_0_f9740686d739025c = function() {
5132
- const ret = /* @__PURE__ */ new Date();
5133
- return addHeapObject(ret);
5134
- };
5135
- imports.wbg.__wbg_new_1acc0b6eea89d040 = function() {
5136
- const ret = new Object();
5137
- return addHeapObject(ret);
5138
- };
5139
- imports.wbg.__wbg_new_2531773dac38ebb3 = function() {
5140
- return handleError(function() {
5141
- const ret = new AbortController();
5142
- return addHeapObject(ret);
5143
- }, arguments);
5144
- };
5145
- imports.wbg.__wbg_new_3c3d849046688a66 = function(arg0, arg1) {
5146
- try {
5147
- var state0 = { a: arg0, b: arg1 };
5148
- var cb0 = (arg02, arg12) => {
5149
- const a = state0.a;
5150
- state0.a = 0;
5151
- try {
5152
- return __wasm_bindgen_func_elem_14376(a, state0.b, arg02, arg12);
5153
- } finally {
5154
- state0.a = a;
5155
- }
5156
- };
5157
- const ret = new Promise(cb0);
5158
- return addHeapObject(ret);
5159
- } finally {
5160
- state0.a = state0.b = 0;
5161
- }
5162
- };
5163
- imports.wbg.__wbg_new_5a79be3ab53b8aa5 = function(arg0) {
5164
- const ret = new Uint8Array(getObject(arg0));
5165
- return addHeapObject(ret);
5166
- };
5167
- imports.wbg.__wbg_new_881c4fe631eee9ad = function() {
5168
- return handleError(function(arg0, arg1) {
5169
- const ret = new WebSocket(getStringFromWasm0(arg0, arg1));
5170
- return addHeapObject(ret);
5171
- }, arguments);
5172
- };
5173
- imports.wbg.__wbg_new_9edf9838a2def39c = function() {
5174
- return handleError(function() {
5175
- const ret = new Headers();
5176
- return addHeapObject(ret);
5177
- }, arguments);
5178
- };
5179
- imports.wbg.__wbg_new_a7442b4b19c1a356 = function(arg0, arg1) {
5180
- const ret = new Error(getStringFromWasm0(arg0, arg1));
5181
- return addHeapObject(ret);
5182
- };
5183
- imports.wbg.__wbg_new_e17d9f43105b08be = function() {
5184
- const ret = new Array();
5185
- return addHeapObject(ret);
5186
- };
5187
- imports.wbg.__wbg_new_from_slice_92f4d78ca282a2d2 = function(arg0, arg1) {
5188
- const ret = new Uint8Array(getArrayU8FromWasm0(arg0, arg1));
5189
- return addHeapObject(ret);
5190
- };
5191
- imports.wbg.__wbg_new_no_args_ee98eee5275000a4 = function(arg0, arg1) {
5192
- const ret = new Function(getStringFromWasm0(arg0, arg1));
5193
- return addHeapObject(ret);
5194
- };
5195
- imports.wbg.__wbg_new_with_byte_offset_and_length_46e3e6a5e9f9e89b = function(arg0, arg1, arg2) {
5196
- const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
5197
- return addHeapObject(ret);
5198
- };
5199
- imports.wbg.__wbg_new_with_length_01aa0dc35aa13543 = function(arg0) {
5200
- const ret = new Uint8Array(arg0 >>> 0);
5201
- return addHeapObject(ret);
5202
- };
5203
- imports.wbg.__wbg_new_with_str_and_init_0ae7728b6ec367b1 = function() {
5204
- return handleError(function(arg0, arg1, arg2) {
5205
- const ret = new Request(getStringFromWasm0(arg0, arg1), getObject(arg2));
5206
- return addHeapObject(ret);
5207
- }, arguments);
5208
- };
5209
- imports.wbg.__wbg_new_with_str_sequence_57a88eb77393f23f = function() {
5210
- return handleError(function(arg0, arg1, arg2) {
5211
- const ret = new WebSocket(getStringFromWasm0(arg0, arg1), getObject(arg2));
5212
- return addHeapObject(ret);
5213
- }, arguments);
5214
- };
5215
- imports.wbg.__wbg_next_020810e0ae8ebcb0 = function() {
5216
- return handleError(function(arg0) {
5217
- const ret = getObject(arg0).next();
5218
- return addHeapObject(ret);
5219
- }, arguments);
5220
- };
5221
- imports.wbg.__wbg_next_2c826fe5dfec6b6a = function(arg0) {
5222
- const ret = getObject(arg0).next;
5223
- return addHeapObject(ret);
5224
- };
5225
- imports.wbg.__wbg_node_905d3e251edff8a2 = function(arg0) {
5226
- const ret = getObject(arg0).node;
5227
- return addHeapObject(ret);
5228
- };
5229
- imports.wbg.__wbg_now_2c95c9de01293173 = function(arg0) {
5230
- const ret = getObject(arg0).now();
5231
- return ret;
5232
- };
5233
- imports.wbg.__wbg_now_793306c526e2e3b6 = function() {
5234
- const ret = Date.now();
5235
- return ret;
5236
- };
5237
- imports.wbg.__wbg_performance_7a3ffd0b17f663ad = function(arg0) {
5238
- const ret = getObject(arg0).performance;
5239
- return addHeapObject(ret);
5240
- };
5241
- imports.wbg.__wbg_process_dc0fbacc7c1c06f7 = function(arg0) {
5242
- const ret = getObject(arg0).process;
5243
- return addHeapObject(ret);
5244
- };
5245
- imports.wbg.__wbg_prototypesetcall_2a6620b6922694b2 = function(arg0, arg1, arg2) {
5246
- Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), getObject(arg2));
5247
- };
5248
- imports.wbg.__wbg_push_df81a39d04db858c = function(arg0, arg1) {
5249
- const ret = getObject(arg0).push(getObject(arg1));
5250
- return ret;
5251
- };
5252
- imports.wbg.__wbg_queueMicrotask_34d692c25c47d05b = function(arg0) {
5253
- const ret = getObject(arg0).queueMicrotask;
5254
- return addHeapObject(ret);
5255
- };
5256
- imports.wbg.__wbg_queueMicrotask_9d76cacb20c84d58 = function(arg0) {
5257
- queueMicrotask(getObject(arg0));
5258
- };
5259
- imports.wbg.__wbg_randomFillSync_ac0988aba3254290 = function() {
5260
- return handleError(function(arg0, arg1) {
5261
- getObject(arg0).randomFillSync(takeObject(arg1));
5262
- }, arguments);
5263
- };
5264
- imports.wbg.__wbg_read_48f1593df542f968 = function(arg0) {
5265
- const ret = getObject(arg0).read();
5266
- return addHeapObject(ret);
5267
- };
5268
- imports.wbg.__wbg_readyState_97984f126080aeda = function(arg0) {
5269
- const ret = getObject(arg0).readyState;
5270
- return ret;
5271
- };
5272
- imports.wbg.__wbg_reason_1cced37e3a93763e = function(arg0, arg1) {
5273
- const ret = getObject(arg1).reason;
5274
- const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
5275
- const len1 = WASM_VECTOR_LEN;
5276
- getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
5277
- getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
5278
- };
5279
- imports.wbg.__wbg_releaseLock_5d0b5a68887b891d = function(arg0) {
5280
- getObject(arg0).releaseLock();
5281
- };
5282
- imports.wbg.__wbg_removeEventListener_924d9db66a4f775d = function() {
5283
- return handleError(function(arg0, arg1, arg2, arg3) {
5284
- getObject(arg0).removeEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3));
5285
- }, arguments);
5286
- };
5287
- imports.wbg.__wbg_require_60cc747a6bc5215a = function() {
5288
- return handleError(function() {
5289
- const ret = module.require;
5290
- return addHeapObject(ret);
5291
- }, arguments);
5292
- };
5293
- imports.wbg.__wbg_resolve_caf97c30b83f7053 = function(arg0) {
5294
- const ret = Promise.resolve(getObject(arg0));
5295
- return addHeapObject(ret);
5296
- };
5297
- imports.wbg.__wbg_respond_0f4dbf5386f5c73e = function() {
5298
- return handleError(function(arg0, arg1) {
5299
- getObject(arg0).respond(arg1 >>> 0);
5300
- }, arguments);
5301
- };
5302
- imports.wbg.__wbg_send_171576d2f7487517 = function() {
5303
- return handleError(function(arg0, arg1, arg2) {
5304
- getObject(arg0).send(getStringFromWasm0(arg1, arg2));
5305
- }, arguments);
5306
- };
5307
- imports.wbg.__wbg_send_3d2cf376613294f0 = function() {
5308
- return handleError(function(arg0, arg1, arg2) {
5309
- getObject(arg0).send(getArrayU8FromWasm0(arg1, arg2));
5310
- }, arguments);
5311
- };
5312
- imports.wbg.__wbg_setTimeout_4eb823e8b72fbe79 = function() {
5313
- return handleError(function(arg0, arg1, arg2) {
5314
- const ret = getObject(arg0).setTimeout(takeObject(arg1), arg2);
5315
- return addHeapObject(ret);
5316
- }, arguments);
5317
- };
5318
- imports.wbg.__wbg_setTimeout_7bb3429662ab1e70 = function(arg0, arg1) {
5319
- const ret = setTimeout(getObject(arg0), arg1);
5320
- return addHeapObject(ret);
5321
- };
5322
- imports.wbg.__wbg_set_3f1d0b984ed272ed = function(arg0, arg1, arg2) {
5323
- getObject(arg0)[takeObject(arg1)] = takeObject(arg2);
5324
- };
5325
- imports.wbg.__wbg_set_9e6516df7b7d0f19 = function(arg0, arg1, arg2) {
5326
- getObject(arg0).set(getArrayU8FromWasm0(arg1, arg2));
5327
- };
5328
- imports.wbg.__wbg_set_binaryType_9d839cea8fcdc5c3 = function(arg0, arg1) {
5329
- getObject(arg0).binaryType = __wbindgen_enum_BinaryType[arg1];
5330
- };
5331
- imports.wbg.__wbg_set_body_3c365989753d61f4 = function(arg0, arg1) {
5332
- getObject(arg0).body = getObject(arg1);
5333
- };
5334
- imports.wbg.__wbg_set_cache_2f9deb19b92b81e3 = function(arg0, arg1) {
5335
- getObject(arg0).cache = __wbindgen_enum_RequestCache[arg1];
5336
- };
5337
- imports.wbg.__wbg_set_credentials_f621cd2d85c0c228 = function(arg0, arg1) {
5338
- getObject(arg0).credentials = __wbindgen_enum_RequestCredentials[arg1];
5339
- };
5340
- imports.wbg.__wbg_set_handle_event_b2de49ad6c81e3c8 = function(arg0, arg1) {
5341
- getObject(arg0).handleEvent = getObject(arg1);
5342
- };
5343
- imports.wbg.__wbg_set_headers_6926da238cd32ee4 = function(arg0, arg1) {
5344
- getObject(arg0).headers = getObject(arg1);
5345
- };
5346
- imports.wbg.__wbg_set_method_c02d8cbbe204ac2d = function(arg0, arg1, arg2) {
5347
- getObject(arg0).method = getStringFromWasm0(arg1, arg2);
5348
- };
5349
- imports.wbg.__wbg_set_mode_52ef73cfa79639cb = function(arg0, arg1) {
5350
- getObject(arg0).mode = __wbindgen_enum_RequestMode[arg1];
5351
- };
5352
- imports.wbg.__wbg_set_onclose_c09e4f7422de8dae = function(arg0, arg1) {
5353
- getObject(arg0).onclose = getObject(arg1);
5354
- };
5355
- imports.wbg.__wbg_set_onerror_337a3a2db9517378 = function(arg0, arg1) {
5356
- getObject(arg0).onerror = getObject(arg1);
5357
- };
5358
- imports.wbg.__wbg_set_onmessage_8661558551a89792 = function(arg0, arg1) {
5359
- getObject(arg0).onmessage = getObject(arg1);
5360
- };
5361
- imports.wbg.__wbg_set_onopen_efccb9305427b907 = function(arg0, arg1) {
5362
- getObject(arg0).onopen = getObject(arg1);
5363
- };
5364
- imports.wbg.__wbg_set_signal_dda2cf7ccb6bee0f = function(arg0, arg1) {
5365
- getObject(arg0).signal = getObject(arg1);
5366
- };
5367
- imports.wbg.__wbg_signal_4db5aa055bf9eb9a = function(arg0) {
5368
- const ret = getObject(arg0).signal;
5369
- return addHeapObject(ret);
5370
- };
5371
- imports.wbg.__wbg_static_accessor_GLOBAL_89e1d9ac6a1b250e = function() {
5372
- const ret = typeof global === "undefined" ? null : global;
5373
- return isLikeNone(ret) ? 0 : addHeapObject(ret);
5374
- };
5375
- imports.wbg.__wbg_static_accessor_GLOBAL_THIS_8b530f326a9e48ac = function() {
5376
- const ret = typeof globalThis === "undefined" ? null : globalThis;
5377
- return isLikeNone(ret) ? 0 : addHeapObject(ret);
5378
- };
5379
- imports.wbg.__wbg_static_accessor_SELF_6fdf4b64710cc91b = function() {
5380
- const ret = typeof self === "undefined" ? null : self;
5381
- return isLikeNone(ret) ? 0 : addHeapObject(ret);
5382
- };
5383
- imports.wbg.__wbg_static_accessor_WINDOW_b45bfc5a37f6cfa2 = function() {
5384
- const ret = typeof window === "undefined" ? null : window;
5385
- return isLikeNone(ret) ? 0 : addHeapObject(ret);
5386
- };
5387
- imports.wbg.__wbg_status_de7eed5a7a5bfd5d = function(arg0) {
5388
- const ret = getObject(arg0).status;
5389
- return ret;
5390
- };
5391
- imports.wbg.__wbg_stringify_b5fb28f6465d9c3e = function() {
5392
- return handleError(function(arg0) {
5393
- const ret = JSON.stringify(getObject(arg0));
5394
- return addHeapObject(ret);
5395
- }, arguments);
5396
- };
5397
- imports.wbg.__wbg_subarray_480600f3d6a9f26c = function(arg0, arg1, arg2) {
5398
- const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);
5399
- return addHeapObject(ret);
5400
- };
5401
- imports.wbg.__wbg_then_4f46f6544e6b4a28 = function(arg0, arg1) {
5402
- const ret = getObject(arg0).then(getObject(arg1));
5403
- return addHeapObject(ret);
5404
- };
5405
- imports.wbg.__wbg_then_70d05cf780a18d77 = function(arg0, arg1, arg2) {
5406
- const ret = getObject(arg0).then(getObject(arg1), getObject(arg2));
5407
- return addHeapObject(ret);
5408
- };
5409
- imports.wbg.__wbg_url_9bd0af1cd8643de7 = function(arg0, arg1) {
5410
- const ret = getObject(arg1).url;
5411
- const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
5412
- const len1 = WASM_VECTOR_LEN;
5413
- getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
5414
- getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
5415
- };
5416
- imports.wbg.__wbg_url_b36d2a5008eb056f = function(arg0, arg1) {
5417
- const ret = getObject(arg1).url;
5418
- const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
5419
- const len1 = WASM_VECTOR_LEN;
5420
- getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
5421
- getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
5422
- };
5423
- imports.wbg.__wbg_value_692627309814bb8c = function(arg0) {
5424
- const ret = getObject(arg0).value;
5425
- return addHeapObject(ret);
5426
- };
5427
- imports.wbg.__wbg_versions_c01dfd4722a88165 = function(arg0) {
5428
- const ret = getObject(arg0).versions;
5429
- return addHeapObject(ret);
5430
- };
5431
- imports.wbg.__wbg_view_f6c15ac9fed63bbd = function(arg0) {
5432
- const ret = getObject(arg0).view;
5433
- return isLikeNone(ret) ? 0 : addHeapObject(ret);
5434
- };
5435
- imports.wbg.__wbg_wasClean_3d7c0cf05bd0a123 = function(arg0) {
5436
- const ret = getObject(arg0).wasClean;
5437
- return ret;
5438
- };
5439
- imports.wbg.__wbindgen_cast_0b4723bb5ff7475b = function(arg0, arg1) {
5440
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_11664, __wasm_bindgen_func_elem_11688);
5441
- return addHeapObject(ret);
5442
- };
5443
- imports.wbg.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) {
5444
- const ret = getStringFromWasm0(arg0, arg1);
5445
- return addHeapObject(ret);
5446
- };
5447
- imports.wbg.__wbindgen_cast_253c73f2760a05aa = function(arg0, arg1) {
5448
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_6219, __wasm_bindgen_func_elem_6230);
5449
- return addHeapObject(ret);
5450
- };
5451
- imports.wbg.__wbindgen_cast_343835dd8f264af2 = function(arg0, arg1) {
5452
- const ret = makeClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_5735, __wasm_bindgen_func_elem_5748);
5453
- return addHeapObject(ret);
5454
- };
5455
- imports.wbg.__wbindgen_cast_7bacc9fa7d2c65f4 = function(arg0, arg1) {
5456
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_12841, __wasm_bindgen_func_elem_12858);
5457
- return addHeapObject(ret);
5458
- };
5459
- imports.wbg.__wbindgen_cast_88fdcfb6b716b7f8 = function(arg0, arg1) {
5460
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_12896, __wasm_bindgen_func_elem_12912);
5461
- return addHeapObject(ret);
5462
- };
5463
- imports.wbg.__wbindgen_cast_c43a1cf1b94f2e7c = function(arg0, arg1) {
5464
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_2083, __wasm_bindgen_func_elem_2287);
5465
- return addHeapObject(ret);
5466
- };
5467
- imports.wbg.__wbindgen_cast_cb9088102bce6b30 = function(arg0, arg1) {
5468
- const ret = getArrayU8FromWasm0(arg0, arg1);
5469
- return addHeapObject(ret);
5470
- };
5471
- imports.wbg.__wbindgen_cast_d6cd19b81560fd6e = function(arg0) {
5472
- const ret = arg0;
5473
- return addHeapObject(ret);
5474
- };
5475
- imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
5476
- const ret = getObject(arg0);
5477
- return addHeapObject(ret);
5478
- };
5479
- imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
5480
- takeObject(arg0);
5481
- };
5482
- return imports;
5483
- }
5484
- function __wbg_finalize_init(instance, module2) {
5485
- wasm = instance.exports;
5486
- __wbg_init.__wbindgen_wasm_module = module2;
5487
- cachedDataViewMemory0 = null;
5488
- cachedUint8ArrayMemory0 = null;
5489
- return wasm;
5490
- }
5491
- async function __wbg_init(module_or_path) {
5492
- if (wasm !== void 0) return wasm;
5493
- if (typeof module_or_path !== "undefined") {
5494
- if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
5495
- ({ module_or_path } = module_or_path);
5496
- } else {
5497
- console.warn("using deprecated parameters for the initialization function; pass a single object instead");
5498
- }
5499
- }
5500
- if (typeof module_or_path === "undefined") {
5501
- module_or_path = "/ermis_call_node_wasm_bg.wasm";
5502
- }
5503
- const imports = __wbg_get_imports();
5504
- if (typeof module_or_path === "string" || typeof Request === "function" && module_or_path instanceof Request || typeof URL === "function" && module_or_path instanceof URL) {
5505
- module_or_path = fetch(module_or_path);
5506
- }
5507
- const { instance, module: module2 } = await __wbg_load(await module_or_path, imports);
5508
- return __wbg_finalize_init(instance, module2);
5509
- }
5510
- var ermis_call_node_wasm_default = __wbg_init;
5511
-
5512
- // src/media_stream_sender.ts
5513
- var MediaStreamSender = class {
5514
- videoEncoder = null;
5515
- audioEncoder = null;
5516
- videoReader = null;
5517
- localStream = null;
5518
- videoConfig = null;
5519
- audioConfig = null;
5520
- videoConfigSent = false;
5521
- audioConfigSent = false;
5522
- hasVideo = false;
5523
- hasAudio = false;
5524
- forceKeyFrame = false;
5525
- nodeCall;
5526
- constructor(nodeCall) {
5527
- this.nodeCall = nodeCall;
5528
- }
5529
- /**
5530
- * Bắt đầu xử lý MediaStream
5531
- */
5532
- async connect(address) {
5533
- try {
5534
- await this.nodeCall.connect(address);
5535
- await this.sendConnected();
5536
- await this.sendConfigs();
5537
- } catch (error) {
5538
- console.error("Error starting MediaStreamSender:", error);
5539
- }
5540
- }
5541
- async sendConfigs() {
5542
- try {
5543
- await this.sendTransceiverState(this.hasAudio, this.hasVideo);
5544
- await this.sendAudioConfig();
5545
- const videoTrack = this.localStream?.getVideoTracks()[0];
5546
- if (videoTrack) {
5547
- await this.sendVideoConfig();
5548
- }
5549
- } catch (error) {
5550
- console.error("Error sending configs:", error);
5551
- }
5552
- }
5553
- /**
5554
- * Dừng và reset encoders
5555
- */
5556
- stop = () => {
5557
4508
  if (this.videoReader) {
5558
4509
  try {
5559
4510
  this.videoReader.cancel("Stream stopped").catch(() => {
@@ -5582,6 +4533,14 @@ var MediaStreamSender = class {
5582
4533
  }
5583
4534
  this.audioEncoder = null;
5584
4535
  }
4536
+ if (this.audioReader) {
4537
+ try {
4538
+ this.audioReader.cancel("Stream stopped").catch(() => {
4539
+ });
4540
+ } catch (e) {
4541
+ }
4542
+ this.audioReader = null;
4543
+ }
5585
4544
  this.videoConfig = null;
5586
4545
  this.audioConfig = null;
5587
4546
  this.videoConfigSent = false;
@@ -5610,22 +4569,29 @@ var MediaStreamSender = class {
5610
4569
  numberOfChannels: metadata.decoderConfig.numberOfChannels ?? 1,
5611
4570
  ...description && { description }
5612
4571
  };
4572
+ this.sendAudioConfig();
5613
4573
  }
5614
4574
  if (chunk && this.isReadyToSendData("audio")) {
4575
+ if (this.isSendingAudio) return;
4576
+ this.isSendingAudio = true;
5615
4577
  const data = new ArrayBuffer(chunk.byteLength);
5616
4578
  chunk.copyTo(data);
5617
4579
  const timestamp = chunk.timestamp;
5618
4580
  const packet = createPacketWithHeader(data, timestamp, "audio", null);
5619
- this.sendPacketOrQueue(packet, "audio", null);
4581
+ this.sendPacketOrQueue(packet, "audio", null).finally(() => {
4582
+ this.isSendingAudio = false;
4583
+ });
5620
4584
  }
5621
4585
  },
5622
4586
  error: (e) => console.error("AudioEncoder error:", e)
5623
4587
  });
5624
4588
  audioEncoder.configure({
5625
4589
  codec: "mp4a.40.2",
4590
+ // codec: 'opus',
5626
4591
  sampleRate: 48e3,
5627
4592
  numberOfChannels: 1,
5628
4593
  bitrate: 128e3
4594
+ // bitrate: 64000,
5629
4595
  });
5630
4596
  this.audioEncoder = audioEncoder;
5631
4597
  this.processAudioFrames(audioTrack);
@@ -5657,12 +4623,16 @@ var MediaStreamSender = class {
5657
4623
  await this.sendVideoConfig();
5658
4624
  }
5659
4625
  if (chunk && this.isReadyToSendData("video")) {
4626
+ if (this.isSendingVideo) return;
4627
+ this.isSendingVideo = true;
5660
4628
  const data = new ArrayBuffer(chunk.byteLength);
5661
4629
  chunk.copyTo(data);
5662
4630
  const frameType = chunk.type === "key" ? "video-key" : "video-delta";
5663
4631
  const timestamp = chunk.timestamp;
5664
4632
  const packet = createPacketWithHeader(data, timestamp, frameType, null);
5665
- this.sendPacketOrQueue(packet, "video", frameType);
4633
+ this.sendPacketOrQueue(packet, "video", frameType).finally(() => {
4634
+ this.isSendingVideo = false;
4635
+ });
5666
4636
  }
5667
4637
  },
5668
4638
  error: (e) => console.error("VideoEncoder error:", e)
@@ -5710,6 +4680,13 @@ var MediaStreamSender = class {
5710
4680
  }
5711
4681
  }
5712
4682
  async replaceAudioTrack(track) {
4683
+ if (this.audioReader) {
4684
+ try {
4685
+ await this.audioReader.cancel("Replacing audio track");
4686
+ } catch (e) {
4687
+ }
4688
+ this.audioReader = null;
4689
+ }
5713
4690
  if (track) {
5714
4691
  this.processAudioFrames(track);
5715
4692
  }
@@ -5764,10 +4741,11 @@ var MediaStreamSender = class {
5764
4741
  };
5765
4742
  processAudioFrames = async (audioTrack) => {
5766
4743
  const audioProcessor = new MediaStreamTrackProcessor({ track: audioTrack });
5767
- const audioReader = audioProcessor.readable.getReader();
4744
+ this.audioReader = audioProcessor.readable.getReader();
5768
4745
  try {
5769
4746
  while (true) {
5770
- const { done, value: frame } = await audioReader.read();
4747
+ if (!this.audioReader) break;
4748
+ const { done, value: frame } = await this.audioReader.read();
5771
4749
  if (done) break;
5772
4750
  if (!this.audioEncoder) {
5773
4751
  frame?.close();
@@ -5785,6 +4763,13 @@ var MediaStreamSender = class {
5785
4763
  }
5786
4764
  } catch (error) {
5787
4765
  console.error(`Error processing audio frames: ${error.message}`);
4766
+ } finally {
4767
+ if (this.audioReader) {
4768
+ try {
4769
+ this.audioReader.releaseLock();
4770
+ } catch (e) {
4771
+ }
4772
+ }
5788
4773
  }
5789
4774
  };
5790
4775
  isReadyToSendData = (type) => {
@@ -5824,6 +4809,22 @@ var MediaStreamSender = class {
5824
4809
  const configPacket = createPacketWithHeader(null, null, "connected", null);
5825
4810
  await this.nodeCall.sendControlFrame(configPacket);
5826
4811
  };
4812
+ startHealthCallInterval = () => {
4813
+ if (this.healthCallInterval) {
4814
+ clearInterval(this.healthCallInterval);
4815
+ }
4816
+ this.healthCallInterval = setInterval(() => {
4817
+ this.sendHealthCall().catch(() => {
4818
+ });
4819
+ }, 5e3);
4820
+ };
4821
+ sendHealthCall = async () => {
4822
+ try {
4823
+ const packet = createPacketWithHeader(null, null, "healthCall", null);
4824
+ await this.nodeCall.sendControlFrame(packet);
4825
+ } catch (e) {
4826
+ }
4827
+ };
5827
4828
  sendPacketOrQueue = async (packet, type, frameType) => {
5828
4829
  if (!this.isReadyToSendData(type)) {
5829
4830
  return;
@@ -6049,8 +5050,8 @@ var HEVCDecoderConfigurationRecord = class _HEVCDecoderConfigurationRecord {
6049
5050
  };
6050
5051
 
6051
5052
  // src/media_stream_receiver.ts
6052
- var MAX_AUDIO_LATENCY = 0.1;
6053
- var MIN_BUFFER_AHEAD = 0.02;
5053
+ var MAX_AUDIO_LATENCY = 0.5;
5054
+ var MIN_BUFFER_AHEAD = 0.05;
6054
5055
  var MediaStreamReceiver = class {
6055
5056
  videoDecoder = null;
6056
5057
  audioDecoder = null;
@@ -6058,9 +5059,12 @@ var MediaStreamReceiver = class {
6058
5059
  videoWriter = null;
6059
5060
  audioContext = null;
6060
5061
  mediaDestination = null;
5062
+ scheduledAudioNodes = [];
6061
5063
  isWaitingForKeyFrame = true;
6062
5064
  nextStartTime = 0;
6063
5065
  lastVideoConfig = null;
5066
+ lastVideoConfigStr = "";
5067
+ lastAudioConfigStr = "";
6064
5068
  nodeCall;
6065
5069
  events;
6066
5070
  generatedStream = null;
@@ -6146,14 +5150,17 @@ var MediaStreamReceiver = class {
6146
5150
  console.error("\u274C VideoDecoder CRASHED:", err);
6147
5151
  this.isWaitingForKeyFrame = true;
6148
5152
  if (this.videoWriter) {
6149
- console.log("\u267B\uFE0F Attempting to respawn VideoDecoder...");
6150
- this.setupVideoDecoder();
6151
- if (this.lastVideoConfig && this.videoDecoder) {
6152
- try {
6153
- this.videoDecoder.configure(this.lastVideoConfig);
6154
- } catch (configErr) {
5153
+ console.log("\u267B\uFE0F Scheduled VideoDecoder respawn in 1000ms...");
5154
+ setTimeout(() => {
5155
+ if (!this.videoWriter) return;
5156
+ this.setupVideoDecoder();
5157
+ if (this.lastVideoConfig && this.videoDecoder) {
5158
+ try {
5159
+ this.videoDecoder.configure(this.lastVideoConfig);
5160
+ } catch (configErr) {
5161
+ }
6155
5162
  }
6156
- }
5163
+ }, 1e3);
6157
5164
  }
6158
5165
  }
6159
5166
  });
@@ -6169,21 +5176,38 @@ var MediaStreamReceiver = class {
6169
5176
  const duration = numberOfFrames / sampleRate;
6170
5177
  const currentTime = this.audioContext.currentTime;
6171
5178
  if (this.nextStartTime < currentTime) {
6172
- this.nextStartTime = currentTime;
5179
+ this.nextStartTime = currentTime + MIN_BUFFER_AHEAD;
6173
5180
  } else if (this.nextStartTime > currentTime + MAX_AUDIO_LATENCY) {
6174
5181
  this.nextStartTime = currentTime + MIN_BUFFER_AHEAD;
5182
+ this.scheduledAudioNodes.forEach((node) => {
5183
+ try {
5184
+ node.stop();
5185
+ } catch (e) {
5186
+ }
5187
+ });
5188
+ this.scheduledAudioNodes = [];
6175
5189
  }
6176
5190
  const audioBuffer = this.audioContext.createBuffer(numberOfChannels, numberOfFrames, sampleRate);
6177
- const size = numberOfChannels * numberOfFrames;
6178
- const tempBuffer = new Float32Array(size);
6179
- audioData.copyTo(tempBuffer, { planeIndex: 0, format: "f32-planar" });
6180
5191
  for (let ch = 0; ch < numberOfChannels; ch++) {
6181
- const channelData = tempBuffer.subarray(ch * numberOfFrames, (ch + 1) * numberOfFrames);
5192
+ const channelData = new Float32Array(numberOfFrames);
5193
+ audioData.copyTo(channelData, { planeIndex: ch, format: "f32-planar" });
6182
5194
  audioBuffer.copyToChannel(channelData, ch);
6183
5195
  }
6184
5196
  const source = this.audioContext.createBufferSource();
6185
5197
  source.buffer = audioBuffer;
6186
5198
  source.connect(this.mediaDestination);
5199
+ this.scheduledAudioNodes.push(source);
5200
+ if (this.scheduledAudioNodes.length > 100) {
5201
+ const oldestNode = this.scheduledAudioNodes.shift();
5202
+ try {
5203
+ oldestNode?.stop();
5204
+ oldestNode?.disconnect();
5205
+ } catch (e) {
5206
+ }
5207
+ }
5208
+ source.onended = () => {
5209
+ this.scheduledAudioNodes = this.scheduledAudioNodes.filter((n) => n !== source);
5210
+ };
6187
5211
  source.start(this.nextStartTime);
6188
5212
  this.nextStartTime += duration;
6189
5213
  audioData.close();
@@ -6204,7 +5228,12 @@ var MediaStreamReceiver = class {
6204
5228
  // Vòng lặp chính xử lý dữ liệu
6205
5229
  receiveLoop = async () => {
6206
5230
  const textDecoder = new TextDecoder();
5231
+ let lastYieldTime = Date.now();
6207
5232
  while (true) {
5233
+ if (Date.now() - lastYieldTime > 16) {
5234
+ await new Promise((resolve) => setTimeout(resolve, 0));
5235
+ lastYieldTime = Date.now();
5236
+ }
6208
5237
  try {
6209
5238
  if (!this.nodeCall) break;
6210
5239
  const data = await this.nodeCall.asyncRecv();
@@ -6218,7 +5247,8 @@ var MediaStreamReceiver = class {
6218
5247
  5 /* ORIENTATION */,
6219
5248
  8 /* REQUEST_CONFIG */,
6220
5249
  9 /* REQUEST_KEY_FRAME */,
6221
- 10 /* END_CALL */
5250
+ 10 /* END_CALL */,
5251
+ 11 /* HEALTH_CALL */
6222
5252
  ].includes(frameType) ? 1 : 9;
6223
5253
  const payload = new Uint8Array(data.buffer, data.byteOffset + payloadOffset, data.byteLength - payloadOffset);
6224
5254
  switch (frameType) {
@@ -6226,8 +5256,12 @@ var MediaStreamReceiver = class {
6226
5256
  case 0 /* VIDEO_CONFIG */: {
6227
5257
  try {
6228
5258
  const videoConfigStr = textDecoder.decode(payload);
5259
+ if (this.lastVideoConfigStr === videoConfigStr && this.videoDecoder?.state === "configured") {
5260
+ break;
5261
+ }
5262
+ this.lastVideoConfigStr = videoConfigStr;
6229
5263
  const videoConfig = JSON.parse(videoConfigStr);
6230
- console.log("--videoConfig--", videoConfig);
5264
+ console.log("videoConfig", videoConfig);
6231
5265
  if (!this.videoWriter) {
6232
5266
  const videoTrackGenerator = new MediaStreamTrackGenerator({ kind: "video" });
6233
5267
  this.videoWriter = videoTrackGenerator.writable.getWriter();
@@ -6280,14 +5314,23 @@ var MediaStreamReceiver = class {
6280
5314
  }
6281
5315
  // --- AUDIO CONFIG ---
6282
5316
  case 1 /* AUDIO_CONFIG */: {
6283
- const audioConfig = JSON.parse(textDecoder.decode(payload));
6284
- console.log("--audioConfig--", audioConfig);
6285
- if (this.audioDecoder?.state !== "closed") {
6286
- this.audioDecoder?.configure({
6287
- codec: audioConfig.codec,
6288
- sampleRate: audioConfig.sampleRate,
6289
- numberOfChannels: audioConfig.numberOfChannels
6290
- });
5317
+ try {
5318
+ const audioConfigStr = textDecoder.decode(payload);
5319
+ if (this.lastAudioConfigStr === audioConfigStr && this.audioDecoder?.state === "configured") {
5320
+ break;
5321
+ }
5322
+ this.lastAudioConfigStr = audioConfigStr;
5323
+ const audioConfig = JSON.parse(audioConfigStr);
5324
+ console.log("audioConfig", audioConfig);
5325
+ if (this.audioDecoder?.state !== "closed") {
5326
+ this.audioDecoder?.configure({
5327
+ codec: audioConfig.codec,
5328
+ sampleRate: audioConfig.sampleRate,
5329
+ numberOfChannels: audioConfig.numberOfChannels
5330
+ });
5331
+ }
5332
+ } catch (e) {
5333
+ console.error("\u274C Error processing AUDIO_CONFIG:", e);
6291
5334
  }
6292
5335
  break;
6293
5336
  }
@@ -6298,11 +5341,9 @@ var MediaStreamReceiver = class {
6298
5341
  const isKeyFrame = frameType === 2 /* VIDEO_KEY */;
6299
5342
  if (this.isWaitingForKeyFrame) {
6300
5343
  if (!isKeyFrame) break;
6301
- console.log("\u2705 Resumed decoding at KeyFrame");
6302
5344
  this.isWaitingForKeyFrame = false;
6303
5345
  }
6304
- if (!isKeyFrame && this.videoDecoder.decodeQueueSize > 15) {
6305
- console.warn("\u26A0\uFE0F Queue > 15. Dropping & Waiting for KeyFrame...");
5346
+ if (!isKeyFrame && this.videoDecoder.decodeQueueSize > 5) {
6306
5347
  this.isWaitingForKeyFrame = true;
6307
5348
  break;
6308
5349
  }
@@ -6382,12 +5423,12 @@ var MediaStreamReceiver = class {
6382
5423
  this.events.onEndCall();
6383
5424
  }
6384
5425
  break;
5426
+ case 11 /* HEALTH_CALL */:
5427
+ break;
6385
5428
  default:
6386
- console.warn("\u2753 Unknown frame type received:", frameType);
6387
5429
  break;
6388
5430
  }
6389
5431
  } catch (error) {
6390
- console.error("Stream loop error", error);
6391
5432
  await new Promise((r) => setTimeout(r, 200));
6392
5433
  }
6393
5434
  }
@@ -6431,6 +5472,13 @@ var MediaStreamReceiver = class {
6431
5472
  }
6432
5473
  this.audioContext = null;
6433
5474
  }
5475
+ this.scheduledAudioNodes.forEach((node) => {
5476
+ try {
5477
+ node.stop();
5478
+ } catch (e) {
5479
+ }
5480
+ });
5481
+ this.scheduledAudioNodes = [];
6434
5482
  this.isWaitingForKeyFrame = true;
6435
5483
  this.mediaDestination = null;
6436
5484
  this.nextStartTime = 0;
@@ -6445,6 +5493,7 @@ var MediaStreamReceiver = class {
6445
5493
  // src/ermis_call_node.ts
6446
5494
  var ErmisCallNode = class {
6447
5495
  wasmPath;
5496
+ workerPath;
6448
5497
  relayUrl = "https://test-iroh.ermis.network.:8443";
6449
5498
  /** Reference to the Ermis Chat client instance */
6450
5499
  _client;
@@ -6454,8 +5503,10 @@ var ErmisCallNode = class {
6454
5503
  cid;
6455
5504
  /** Type of call: 'audio' or 'video' */
6456
5505
  callType;
6457
- /** ID of the current user */
6458
- userID;
5506
+ /** ID of the current user — always reads live value from client */
5507
+ get userID() {
5508
+ return this._client?.userID;
5509
+ }
6459
5510
  /** Current status of the call */
6460
5511
  callStatus = "";
6461
5512
  metadata;
@@ -6521,34 +5572,37 @@ var ErmisCallNode = class {
6521
5572
  isDestroyed = false;
6522
5573
  mediaSender = null;
6523
5574
  mediaReceiver = null;
6524
- constructor(client, sessionID, wasmPath, relayUrl) {
5575
+ constructor(client, sessionID, wasmPath, relayUrl, workerPath) {
6525
5576
  this._client = client;
6526
5577
  this.cid = "";
6527
5578
  this.callType = "";
6528
5579
  this.sessionID = sessionID;
6529
- this.userID = client.userID;
6530
5580
  this.metadata = {};
6531
5581
  this.wasmPath = wasmPath;
6532
5582
  this.relayUrl = relayUrl;
5583
+ this.workerPath = workerPath || "/wasm_worker.worker.mjs";
6533
5584
  this.listenSocketEvents();
6534
5585
  this.setupDeviceChangeListener();
6535
5586
  this.loadWasm();
6536
5587
  }
6537
5588
  async loadWasm() {
6538
5589
  try {
6539
- await ermis_call_node_wasm_default(this.wasmPath);
5590
+ this.callNode = new WasmWorkerProxy(new URL(this.workerPath, window.location.origin));
5591
+ await this.callNode.init(this.wasmPath);
6540
5592
  } catch (error) {
6541
- console.error("Failed to load ErmisCall WASM module:", error);
5593
+ console.error("Failed to load ErmisCall WASM Worker:", error);
6542
5594
  throw error;
6543
5595
  }
6544
5596
  }
6545
5597
  async initialize() {
6546
5598
  try {
6547
- const node = new ErmisCall();
6548
- await node.spawn([this.relayUrl]);
6549
- this.callNode = node;
6550
- this.mediaSender = new MediaStreamSender(node);
6551
- this.mediaReceiver = new MediaStreamReceiver(node, {
5599
+ if (!this.callNode) {
5600
+ await this.loadWasm();
5601
+ }
5602
+ const proxy = this.callNode;
5603
+ await proxy.spawn([this.relayUrl]);
5604
+ this.mediaSender = new MediaStreamSender(proxy);
5605
+ this.mediaReceiver = new MediaStreamReceiver(proxy, {
6552
5606
  onConnected: () => {
6553
5607
  this.setCallStatus("connected" /* CONNECTED */);
6554
5608
  this.connectCall();
@@ -6583,7 +5637,8 @@ var ErmisCallNode = class {
6583
5637
  this.destroy();
6584
5638
  }
6585
5639
  });
6586
- return node;
5640
+ await proxy.startRecvLoop();
5641
+ return proxy;
6587
5642
  } catch (error) {
6588
5643
  console.error("Failed to initialize Ermis SDK:", error);
6589
5644
  throw error;
@@ -6626,13 +5681,13 @@ var ErmisCallNode = class {
6626
5681
  if (typeof this.onError === "function") {
6627
5682
  if (error.code === "ERR_NETWORK") {
6628
5683
  if (action === "create-call" /* CREATE_CALL */) {
6629
- this.onError("Unable to make the call. Please check your network connection");
5684
+ this.onError("call_network_error");
6630
5685
  }
6631
5686
  } else {
6632
5687
  if (error.response.data.ermis_code === 20) {
6633
- this.onError("Recipient was busy");
5688
+ this.onError("call_recipient_busy");
6634
5689
  } else {
6635
- const errMsg = error.response.data?.message ? error.response.data?.message : "Call failed";
5690
+ const errMsg = error.response.data?.message ? error.response.data?.message : "call_failed";
6636
5691
  this.onError(errMsg);
6637
5692
  }
6638
5693
  }
@@ -6699,7 +5754,7 @@ var ErmisCallNode = class {
6699
5754
  }
6700
5755
  }
6701
5756
  if (typeof this.onError === "function") {
6702
- this.onError("No microphone or camera found. Please check your device.");
5757
+ this.onError("call_no_devices");
6703
5758
  }
6704
5759
  return null;
6705
5760
  }
@@ -6730,20 +5785,25 @@ var ErmisCallNode = class {
6730
5785
  setUserInfo(cid, eventUserId) {
6731
5786
  if (!cid || !eventUserId) return;
6732
5787
  const channel = cid ? this.getClient().activeChannels[cid] : void 0;
6733
- const members = channel?.state?.members || {};
6734
- const memberIds = Object.keys(members);
5788
+ const stateMembers = channel?.state?.members || {};
5789
+ const memberIds = Object.keys(stateMembers);
6735
5790
  const callerId = eventUserId || "";
6736
5791
  const receiverId = memberIds.find((id) => id !== callerId) || "";
6737
- const callerUser = this.getClient().state.users[callerId];
6738
- const receiverUser = this.getClient().state.users[receiverId];
5792
+ const dataMembers = channel?.data?.members || [];
5793
+ const findUserFromDataMembers = (userId) => {
5794
+ const member = dataMembers.find((m) => m.user_id === userId || m.user?.id === userId);
5795
+ return member?.user;
5796
+ };
5797
+ const callerUser = findUserFromDataMembers(callerId) || stateMembers[callerId]?.user || this.getClient().state.users[callerId];
5798
+ const receiverUser = findUserFromDataMembers(receiverId) || stateMembers[receiverId]?.user || this.getClient().state.users[receiverId];
6739
5799
  this.callerInfo = {
6740
5800
  id: callerId,
6741
- name: callerUser?.name,
5801
+ name: callerUser?.name || callerId,
6742
5802
  avatar: callerUser?.avatar || ""
6743
5803
  };
6744
5804
  this.receiverInfo = {
6745
5805
  id: receiverId,
6746
- name: receiverUser?.name,
5806
+ name: receiverUser?.name || receiverId,
6747
5807
  avatar: receiverUser?.avatar || ""
6748
5808
  };
6749
5809
  }
@@ -6761,7 +5821,6 @@ var ErmisCallNode = class {
6761
5821
  this.callStatus = "";
6762
5822
  this.callType = is_video ? "video" : "audio";
6763
5823
  this.setUserInfo(cid, eventUserId);
6764
- this.setCallStatus("ringing" /* RINGING */);
6765
5824
  this.cid = cid || "";
6766
5825
  this.metadata = metadata || {};
6767
5826
  if (typeof this.onCallEvent === "function") {
@@ -6774,15 +5833,12 @@ var ErmisCallNode = class {
6774
5833
  metadata: this.metadata
6775
5834
  });
6776
5835
  }
5836
+ this.setCallStatus("ringing" /* RINGING */);
6777
5837
  await this.startLocalStream();
6778
5838
  if (this.callStatus === "ended" /* ENDED */) return;
6779
5839
  if (eventUserId !== this.userID) {
6780
5840
  await this.initialize();
6781
5841
  }
6782
- if (this.localStream && this.mediaSender && this.mediaReceiver) {
6783
- this.mediaSender?.initEncoders(this.localStream);
6784
- this.mediaReceiver?.initDecoders(this.callType);
6785
- }
6786
5842
  if (eventUserId === this.userID) {
6787
5843
  if (this.missCallTimeout) clearTimeout(this.missCallTimeout);
6788
5844
  this.missCallTimeout = setTimeout(async () => {
@@ -6800,6 +5856,12 @@ var ErmisCallNode = class {
6800
5856
  if (this.mediaReceiver && this.mediaSender) {
6801
5857
  await this.mediaReceiver.acceptConnection();
6802
5858
  await this.mediaSender.sendConnected();
5859
+ }
5860
+ if (this.localStream && this.mediaSender && this.mediaReceiver && this.callType) {
5861
+ this.mediaSender?.initEncoders(this.localStream);
5862
+ this.mediaReceiver?.initDecoders(this.callType);
5863
+ }
5864
+ if (this.mediaSender) {
6803
5865
  await this.mediaSender.sendConfigs();
6804
5866
  }
6805
5867
  }
@@ -6807,7 +5869,7 @@ var ErmisCallNode = class {
6807
5869
  case "end-call" /* END_CALL */:
6808
5870
  case "reject-call" /* REJECT_CALL */:
6809
5871
  case "miss-call" /* MISS_CALL */:
6810
- this.destroy();
5872
+ await this.destroy();
6811
5873
  break;
6812
5874
  }
6813
5875
  };
@@ -6853,7 +5915,7 @@ var ErmisCallNode = class {
6853
5915
  this._client.on("connection.changed", this.connectionChangedHandler);
6854
5916
  this._client.on("message.updated", this.messageUpdatedHandler);
6855
5917
  }
6856
- cleanupCall() {
5918
+ async cleanupCall() {
6857
5919
  if (this.mediaSender) {
6858
5920
  this.mediaSender?.stop();
6859
5921
  this.mediaSender = null;
@@ -6863,9 +5925,9 @@ var ErmisCallNode = class {
6863
5925
  this.mediaReceiver = null;
6864
5926
  }
6865
5927
  if (this.callNode) {
6866
- this.callNode?.closeEndpoint();
6867
- if (this.callStatus === "connected" /* CONNECTED */) {
6868
- this.callNode?.closeConnection();
5928
+ try {
5929
+ await Promise.race([this.callNode.terminate(), new Promise((resolve) => setTimeout(resolve, 1e3))]);
5930
+ } catch {
6869
5931
  }
6870
5932
  this.callNode = null;
6871
5933
  }
@@ -6903,8 +5965,8 @@ var ErmisCallNode = class {
6903
5965
  }
6904
5966
  this.setCallStatus("ended" /* ENDED */);
6905
5967
  }
6906
- destroy() {
6907
- this.cleanupCall();
5968
+ async destroy() {
5969
+ await this.cleanupCall();
6908
5970
  }
6909
5971
  async getDevices() {
6910
5972
  if (this.availableAudioDevices.length > 0 || this.availableVideoDevices.length > 0) {
@@ -6928,9 +5990,14 @@ var ErmisCallNode = class {
6928
5990
  videoDevice: this.availableVideoDevices[0]
6929
5991
  };
6930
5992
  }
5993
+ prefillUserInfo(cid) {
5994
+ this.setUserInfo(cid, this.userID);
5995
+ }
6931
5996
  async createCall(callType, cid) {
6932
5997
  try {
6933
5998
  this.cid = cid;
5999
+ this.callType = callType;
6000
+ this.prefillUserInfo(cid);
6934
6001
  const address = await this.getLocalEndpointAddr();
6935
6002
  await this._sendSignal({
6936
6003
  action: "create-call" /* CREATE_CALL */,
@@ -6950,6 +6017,13 @@ var ErmisCallNode = class {
6950
6017
  const address = this.metadata?.address || "";
6951
6018
  await this.mediaSender.connect(address);
6952
6019
  }
6020
+ if (this.localStream && this.mediaSender && this.mediaReceiver) {
6021
+ this.mediaSender?.initEncoders(this.localStream);
6022
+ this.mediaReceiver?.initDecoders(this.callType || "audio");
6023
+ }
6024
+ if (this.mediaSender) {
6025
+ await this.mediaSender.sendConfigs();
6026
+ }
6953
6027
  } catch (error) {
6954
6028
  console.error("Failed to accept call:", error);
6955
6029
  throw error;
@@ -7102,12 +6176,16 @@ var ErmisCallNode = class {
7102
6176
  }
7103
6177
  this.selectedAudioDeviceId = deviceId;
7104
6178
  if (!this.localStream) return false;
6179
+ const mediaConstraints = await this.getMediaConstraints();
7105
6180
  const newStream = await navigator.mediaDevices.getUserMedia({
7106
- audio: { deviceId: { exact: deviceId } },
6181
+ audio: mediaConstraints.audio,
7107
6182
  video: false
7108
6183
  });
7109
6184
  const newAudioTrack = newStream.getAudioTracks()[0];
7110
6185
  const oldAudioTrack = this.localStream.getAudioTracks()[0];
6186
+ if (this.mediaSender && newAudioTrack) {
6187
+ await this.mediaSender.replaceAudioTrack(newAudioTrack);
6188
+ }
7111
6189
  if (oldAudioTrack) {
7112
6190
  this.localStream.removeTrack(oldAudioTrack);
7113
6191
  oldAudioTrack.stop();
@@ -7138,12 +6216,16 @@ var ErmisCallNode = class {
7138
6216
  }
7139
6217
  this.selectedVideoDeviceId = deviceId;
7140
6218
  if (!this.localStream) return false;
6219
+ const mediaConstraints = await this.getMediaConstraints();
7141
6220
  const newStream = await navigator.mediaDevices.getUserMedia({
7142
6221
  audio: false,
7143
- video: { deviceId: { exact: deviceId } }
6222
+ video: mediaConstraints.video
7144
6223
  });
7145
6224
  const newVideoTrack = newStream.getVideoTracks()[0];
7146
6225
  const oldVideoTrack = this.localStream.getVideoTracks()[0];
6226
+ if (this.mediaSender && newVideoTrack) {
6227
+ await this.mediaSender.replaceVideoTrack(newVideoTrack);
6228
+ }
7147
6229
  if (oldVideoTrack) {
7148
6230
  this.localStream.removeTrack(oldVideoTrack);
7149
6231
  oldVideoTrack.stop();
@@ -7334,7 +6416,7 @@ var ErmisAuthProvider = class {
7334
6416
  return data;
7335
6417
  }
7336
6418
  getUserAgent() {
7337
- return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.8"}`;
6419
+ return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"2.0.0"}`;
7338
6420
  }
7339
6421
  setUserAgent(userAgent) {
7340
6422
  this.userAgent = userAgent;
@@ -7479,88 +6561,155 @@ var ErmisAuthProvider = class {
7479
6561
  };
7480
6562
 
7481
6563
  // src/system_message.ts
7482
- var DURATION_MAP = {
7483
- "10000": "10 seconds",
7484
- "30000": "30 seconds",
7485
- "60000": "1 minute",
7486
- "300000": "5 minutes",
7487
- "900000": "15 minutes",
7488
- "3600000": "60 minutes"
7489
- };
7490
6564
  function resolveUser(userId, userMap) {
7491
6565
  return userMap[userId] ?? userId;
7492
6566
  }
7493
- function parseSystemMessage(value, userMap) {
6567
+ function parseSystemMessage(value, userMap, translations) {
7494
6568
  if (!value || typeof value !== "string") return value ?? "";
7495
6569
  const trimmed = value.trim();
7496
6570
  if (!trimmed) return "";
7497
6571
  const parts = trimmed.split(" ");
7498
6572
  const formatId = parts[0];
7499
6573
  const userId = parts[1] ?? "";
7500
- const userName = userId ? resolveUser(userId, userMap) : "User";
6574
+ const userName = userId ? resolveUser(userId, userMap) : translations?.userFallback ?? "User";
7501
6575
  switch (formatId) {
7502
6576
  // 1: userName changed the channel name to channelName (may contain spaces)
7503
6577
  case "1": {
7504
6578
  const channelName = parts.slice(2).join(" ");
6579
+ const template = translations?.["1"] ?? translations?.changeName;
6580
+ if (template) {
6581
+ return template.replace("{{user}}", userName).replace("{{channel}}", channelName);
6582
+ }
7505
6583
  return `${userName} changed the channel name to ${channelName}.`;
7506
6584
  }
7507
6585
  // 2–13, 16–17: single-user actions
7508
- case "2":
6586
+ case "2": {
6587
+ const template = translations?.["2"] ?? translations?.changeAvatar;
6588
+ if (template) return template.replace("{{user}}", userName);
7509
6589
  return `${userName} changed the channel avatar.`;
7510
- case "3":
6590
+ }
6591
+ case "3": {
6592
+ const template = translations?.["3"] ?? translations?.changeDescription;
6593
+ if (template) return template.replace("{{user}}", userName);
7511
6594
  return `${userName} changed the channel description.`;
7512
- case "4":
6595
+ }
6596
+ case "4": {
6597
+ const template = translations?.["4"] ?? translations?.removed;
6598
+ if (template) return template.replace("{{user}}", userName);
7513
6599
  return `${userName} was removed from the channel.`;
7514
- case "5":
6600
+ }
6601
+ case "5": {
6602
+ const template = translations?.["5"] ?? translations?.banned;
6603
+ if (template) return template.replace("{{user}}", userName);
7515
6604
  return `${userName} was banned.`;
7516
- case "6":
6605
+ }
6606
+ case "6": {
6607
+ const template = translations?.["6"] ?? translations?.unbanned;
6608
+ if (template) return template.replace("{{user}}", userName);
7517
6609
  return `${userName} was unbanned.`;
7518
- case "7":
6610
+ }
6611
+ case "7": {
6612
+ const template = translations?.["7"] ?? translations?.promoted;
6613
+ if (template) return template.replace("{{user}}", userName);
7519
6614
  return `${userName} was promoted to moderator.`;
7520
- case "8":
6615
+ }
6616
+ case "8": {
6617
+ const template = translations?.["8"] ?? translations?.demoted;
6618
+ if (template) return template.replace("{{user}}", userName);
7521
6619
  return `${userName} was demoted from moderator.`;
7522
- case "9":
6620
+ }
6621
+ case "9": {
6622
+ const template = translations?.["9"] ?? translations?.permissionsUpdated;
6623
+ if (template) return template.replace("{{user}}", userName);
7523
6624
  return `${userName}'s permissions were updated.`;
7524
- case "10":
6625
+ }
6626
+ case "10": {
6627
+ const template = translations?.["10"] ?? translations?.joined;
6628
+ if (template) return template.replace("{{user}}", userName);
7525
6629
  return `${userName} joined the channel.`;
7526
- case "11":
6630
+ }
6631
+ case "11": {
6632
+ const template = translations?.["11"] ?? translations?.declined;
6633
+ if (template) return template.replace("{{user}}", userName);
7527
6634
  return `${userName} declined the channel invitation.`;
7528
- case "12":
6635
+ }
6636
+ case "12": {
6637
+ const template = translations?.["12"] ?? translations?.left;
6638
+ if (template) return template.replace("{{user}}", userName);
7529
6639
  return `${userName} left the channel.`;
7530
- case "13":
6640
+ }
6641
+ case "13": {
6642
+ const template = translations?.["13"] ?? translations?.clearedHistory;
6643
+ if (template) return template.replace("{{user}}", userName);
7531
6644
  return `${userName} cleared the chat history.`;
6645
+ }
7532
6646
  // 14: channel type change (true = public, false = private)
7533
6647
  case "14": {
7534
6648
  const rawType = parts[2] ?? "";
7535
- const channelType = rawType === "true" ? "public" : "private";
6649
+ const typeKey = rawType === "true" ? "public" : "private";
6650
+ const channelType = translations?.[typeKey] ?? typeKey;
6651
+ const template = translations?.["14"] ?? translations?.changeType;
6652
+ if (template) {
6653
+ return template.replace("{{user}}", userName).replace("{{type}}", channelType);
6654
+ }
7536
6655
  return `${userName} changed the channel to ${channelType}.`;
7537
6656
  }
7538
- // 15: cooldown toggle / duration
7539
6657
  case "15": {
7540
6658
  const duration = parts[2] ?? "0";
7541
6659
  if (duration === "0") {
6660
+ const template2 = translations?.["15_off"] ?? translations?.cooldownOff;
6661
+ if (template2) return template2.replace("{{user}}", userName);
7542
6662
  return `${userName} disabled cooldown.`;
7543
6663
  }
7544
- const durationText = DURATION_MAP[duration] ?? `${duration}ms`;
6664
+ let durationText = `${duration}ms`;
6665
+ const minLabel = translations?.durationUnitMin ?? "minute";
6666
+ const secLabel = translations?.durationUnitSec ?? "seconds";
6667
+ if (duration === "10000") durationText = `10 ${secLabel}`;
6668
+ else if (duration === "30000") durationText = `30 ${secLabel}`;
6669
+ else if (duration === "60000") durationText = `1 ${minLabel}`;
6670
+ else if (duration === "300000") durationText = `5 ${minLabel}`;
6671
+ else if (duration === "900000") durationText = `15 ${minLabel}`;
6672
+ else if (duration === "3600000") durationText = `60 ${minLabel}`;
6673
+ const template = translations?.["15_on"] ?? translations?.cooldownOn;
6674
+ if (template) {
6675
+ return template.replace("{{user}}", userName).replace("{{duration}}", durationText);
6676
+ }
7545
6677
  return `${userName} enabled cooldown for ${durationText}.`;
7546
6678
  }
7547
- case "16":
6679
+ case "16": {
6680
+ const template = translations?.["16"] ?? translations?.bannedWordsUpdated;
6681
+ if (template) return template.replace("{{user}}", userName);
7548
6682
  return `${userName} updated the banned words.`;
7549
- case "17":
6683
+ }
6684
+ case "17": {
6685
+ const template = translations?.["17"] ?? translations?.added;
6686
+ if (template) return template.replace("{{user}}", userName);
7550
6687
  return `${userName} was added to the channel.`;
6688
+ }
7551
6689
  // 18: admin transfer (two user IDs)
7552
6690
  case "18": {
7553
6691
  const oldUserId = parts[1] ?? "";
7554
6692
  const newUserId = parts[2] ?? "";
7555
- const oldUserName = oldUserId ? resolveUser(oldUserId, userMap) : "User";
7556
- const newUserName = newUserId ? resolveUser(newUserId, userMap) : "User";
7557
- return `Admin ${oldUserName} left and assigned ${newUserName} as the new admin.`;
6693
+ const oldUserName = oldUserId ? resolveUser(oldUserId, userMap) : translations?.userFallback ?? "User";
6694
+ const newUserName = newUserId ? resolveUser(newUserId, userMap) : translations?.userFallback ?? "User";
6695
+ const adminLabel = translations?.adminFallback ?? "Admin";
6696
+ const template = translations?.["18"] ?? translations?.adminTransfer;
6697
+ if (template) {
6698
+ return template.replace("{{user}}", oldUserName).replace("{{targetUser}}", newUserName).replace("{{admin}}", adminLabel);
6699
+ }
6700
+ return `${adminLabel} ${oldUserName} left and assigned ${newUserName} as the new admin.`;
7558
6701
  }
7559
6702
  // 19–20: pin / unpin (userId + msgID)
7560
- case "19":
6703
+ case "19": {
6704
+ const template = translations?.["19"] ?? translations?.pinned;
6705
+ if (template) return template.replace("{{user}}", userName);
7561
6706
  return `${userName} pinned a message.`;
7562
- case "20":
6707
+ }
6708
+ case "20": {
6709
+ const template = translations?.["20"] ?? translations?.unpinned;
6710
+ if (template) return template.replace("{{user}}", userName);
7563
6711
  return `${userName} unpinned a message.`;
6712
+ }
7564
6713
  default:
7565
6714
  return trimmed;
7566
6715
  }
@@ -7571,16 +6720,18 @@ var CallType = {
7571
6720
  AUDIO: "audio",
7572
6721
  VIDEO: "video"
7573
6722
  };
7574
- function formatDuration(durationMs) {
6723
+ function formatDuration(durationMs, translations) {
7575
6724
  if (!durationMs) return "";
7576
6725
  const ms = parseInt(durationMs, 10);
7577
6726
  if (isNaN(ms) || ms <= 0) return "";
7578
6727
  const totalSeconds = Math.floor(ms / 1e3);
7579
6728
  const minutes = Math.floor(totalSeconds / 60);
7580
6729
  const seconds = totalSeconds % 60;
7581
- return `${minutes} min, ${seconds} sec`;
6730
+ const minUnit = translations?.durationUnitMin ?? "min";
6731
+ const secUnit = translations?.durationUnitSec ?? "sec";
6732
+ return `${minutes} ${minUnit}, ${seconds} ${secUnit}`;
7582
6733
  }
7583
- function parseSignalMessage(value, myUserId) {
6734
+ function parseSignalMessage(value, myUserId, translations) {
7584
6735
  if (!value || typeof value !== "string") return null;
7585
6736
  const trimmed = value.trim();
7586
6737
  if (!trimmed) return null;
@@ -7599,70 +6750,70 @@ function parseSignalMessage(value, myUserId) {
7599
6750
  let text;
7600
6751
  switch (number) {
7601
6752
  case 1:
7602
- text = isMe ? "Calling..." : "Incoming audio call...";
6753
+ text = isMe ? translations?.calling ?? "Calling..." : translations?.incomingAudioCall ?? "Incoming audio call...";
7603
6754
  callType = CallType.AUDIO;
7604
6755
  color = "#54D62C";
7605
6756
  break;
7606
6757
  case 2:
7607
- text = isMe ? "Outgoing audio call" : "You missed audio call";
6758
+ text = isMe ? translations?.outgoingAudioCall ?? "Outgoing audio call" : translations?.missedAudioCall ?? "You missed audio call";
7608
6759
  callType = CallType.AUDIO;
7609
6760
  color = "#FF4842";
7610
6761
  break;
7611
6762
  case 3:
7612
6763
  if (duration) {
7613
- text = isMe ? "Outgoing audio call" : "Incoming audio call";
6764
+ text = isMe ? translations?.outgoingAudioCall ?? "Outgoing audio call" : translations?.incomingAudioCall ?? "Incoming audio call";
7614
6765
  color = "#54D62C";
7615
6766
  } else {
7616
6767
  if (enderId === myUserId) {
7617
- text = "You cancel audio call";
6768
+ text = translations?.cancelAudioCall ?? "You cancel audio call";
7618
6769
  } else {
7619
- text = "You missed audio call";
6770
+ text = translations?.missedAudioCall ?? "You missed audio call";
7620
6771
  }
7621
6772
  color = "#FF4842";
7622
6773
  }
7623
6774
  callType = CallType.AUDIO;
7624
6775
  break;
7625
6776
  case 4:
7626
- text = isMe ? "Calling..." : "Incoming video call...";
6777
+ text = isMe ? translations?.calling ?? "Calling..." : translations?.incomingVideoCall ?? "Incoming video call...";
7627
6778
  callType = CallType.VIDEO;
7628
6779
  color = "#54D62C";
7629
6780
  break;
7630
6781
  case 5:
7631
- text = isMe ? "Outgoing video call" : "You missed video call";
6782
+ text = isMe ? translations?.outgoingVideoCall ?? "Outgoing video call" : translations?.missedVideoCall ?? "You missed video call";
7632
6783
  callType = CallType.VIDEO;
7633
6784
  color = "#FF4842";
7634
6785
  break;
7635
6786
  case 6:
7636
6787
  if (duration) {
7637
- text = isMe ? "Outgoing video call" : "Incoming video call";
6788
+ text = isMe ? translations?.outgoingVideoCall ?? "Outgoing video call" : translations?.incomingVideoCall ?? "Incoming video call";
7638
6789
  color = "#54D62C";
7639
6790
  } else {
7640
6791
  if (enderId === myUserId) {
7641
- text = "You cancel video call";
6792
+ text = translations?.cancelVideoCall ?? "You cancel video call";
7642
6793
  } else {
7643
- text = "You missed video call";
6794
+ text = translations?.missedVideoCall ?? "You missed video call";
7644
6795
  }
7645
6796
  color = "#FF4842";
7646
6797
  }
7647
6798
  callType = CallType.VIDEO;
7648
6799
  break;
7649
6800
  case 7:
7650
- text = isMe ? "Recipient rejected audio call" : "You rejected audio call";
6801
+ text = isMe ? translations?.rejectedAudioCallRecipient ?? "Recipient rejected audio call" : translations?.rejectedAudioCallYou ?? "You rejected audio call";
7651
6802
  callType = CallType.AUDIO;
7652
6803
  color = "#FF4842";
7653
6804
  break;
7654
6805
  case 8:
7655
- text = isMe ? "Recipient rejected video call" : "You rejected video call";
6806
+ text = isMe ? translations?.rejectedVideoCallRecipient ?? "Recipient rejected video call" : translations?.rejectedVideoCallYou ?? "You rejected video call";
7656
6807
  callType = CallType.VIDEO;
7657
6808
  color = "#FF4842";
7658
6809
  break;
7659
6810
  case 9:
7660
- text = isMe ? "Recipient was busy" : "You missed audio call";
6811
+ text = isMe ? translations?.busyRecipient ?? "Recipient was busy" : translations?.missedAudioCall ?? "You missed audio call";
7661
6812
  callType = CallType.AUDIO;
7662
6813
  color = "#FF4842";
7663
6814
  break;
7664
6815
  case 10:
7665
- text = isMe ? "Recipient was busy" : "You missed video call";
6816
+ text = isMe ? translations?.busyRecipient ?? "Recipient was busy" : translations?.missedVideoCall ?? "You missed video call";
7666
6817
  callType = CallType.VIDEO;
7667
6818
  color = "#FF4842";
7668
6819
  break;
@@ -7671,7 +6822,7 @@ function parseSignalMessage(value, myUserId) {
7671
6822
  callType = "";
7672
6823
  color = "";
7673
6824
  }
7674
- return { text, duration: formatDuration(duration), callType, color };
6825
+ return { text, duration: formatDuration(duration, translations), callType, color };
7675
6826
  }
7676
6827
  // Annotate the CommonJS export names for ESM import in node:
7677
6828
  0 && (module.exports = {
@@ -7701,5 +6852,4 @@ function parseSignalMessage(value, myUserId) {
7701
6852
  parseSignalMessage,
7702
6853
  parseSystemMessage
7703
6854
  });
7704
- //! NOTE: check lai o day
7705
6855
  //# sourceMappingURL=index.cjs.map