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