@ai-matrx/meet 0.11.53 → 0.11.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.cjs CHANGED
@@ -2604,6 +2604,10 @@ function personOf(identity) {
2604
2604
  const cut = value.indexOf(CONNECTION_SEPARATOR);
2605
2605
  return cut === -1 ? value : value.slice(0, cut);
2606
2606
  }
2607
+ function userIdOfIdentity(identity) {
2608
+ const person = personOf(identity);
2609
+ return person.startsWith("user:") ? person.slice("user:".length) : null;
2610
+ }
2607
2611
  function isGuestIdentity(identity) {
2608
2612
  return personOf(identity).startsWith("guest:");
2609
2613
  }
@@ -6146,21 +6150,35 @@ function heartbeatIntervalMs(roomSize) {
6146
6150
  function staleAfterMs(roomSize) {
6147
6151
  return heartbeatIntervalMs(roomSize) * 3 + 1e3;
6148
6152
  }
6153
+ function firstBeatAllowanceMs(roomSize) {
6154
+ return staleAfterMs(roomSize) * 2;
6155
+ }
6149
6156
  function createLivenessTracker(now) {
6150
6157
  const lastHeard = /* @__PURE__ */ new Map();
6158
+ const firstSeen = /* @__PURE__ */ new Map();
6151
6159
  const beats = /* @__PURE__ */ new Map();
6152
6160
  return {
6153
6161
  heard(who, beat) {
6154
6162
  lastHeard.set(who, now());
6163
+ firstSeen.delete(who);
6155
6164
  if (beat !== null) beats.set(who, beat);
6156
6165
  },
6166
+ expect(who) {
6167
+ if (!lastHeard.has(who) && !firstSeen.has(who)) firstSeen.set(who, now());
6168
+ },
6157
6169
  stale(present, roomSize) {
6158
6170
  const limit = staleAfterMs(roomSize);
6171
+ const firstLimit = firstBeatAllowanceMs(roomSize);
6159
6172
  const at = now();
6160
6173
  const out = /* @__PURE__ */ new Set();
6161
6174
  for (const who of present) {
6162
6175
  const heard = lastHeard.get(who);
6163
- if (heard !== void 0 && at - heard > limit) out.add(who);
6176
+ if (heard !== void 0) {
6177
+ if (at - heard > limit) out.add(who);
6178
+ continue;
6179
+ }
6180
+ const seen = firstSeen.get(who);
6181
+ if (seen !== void 0 && at - seen > firstLimit) out.add(who);
6164
6182
  }
6165
6183
  return out;
6166
6184
  },
@@ -6168,13 +6186,16 @@ function createLivenessTracker(now) {
6168
6186
  restartClock() {
6169
6187
  const at = now();
6170
6188
  for (const who of lastHeard.keys()) lastHeard.set(who, at);
6189
+ for (const who of firstSeen.keys()) firstSeen.set(who, at);
6171
6190
  },
6172
6191
  forget(who) {
6173
6192
  lastHeard.delete(who);
6193
+ firstSeen.delete(who);
6174
6194
  beats.delete(who);
6175
6195
  },
6176
6196
  clear() {
6177
6197
  lastHeard.clear();
6198
+ firstSeen.clear();
6178
6199
  beats.clear();
6179
6200
  }
6180
6201
  };
@@ -6940,6 +6961,13 @@ function createRoomEngine(options) {
6940
6961
  const previous = new Map(liveRoster.map((p) => [p.identity, p]));
6941
6962
  const present = new Set(list.map((p) => p.identity));
6942
6963
  const graceMs = connectionPolicy.reconnectGraceSeconds * 1e3;
6964
+ if (store.snapshot().phase === "in_call") {
6965
+ for (const [who, last] of previous) {
6966
+ if (last.isLocal || present.has(who) || departures.has(who)) continue;
6967
+ departures.set(who, null);
6968
+ report("warn", `meet: ${who} vanished from the room's roster with no departure event; held as reconnecting`, "The media layer dropped a participant silently; the tile is kept for the reconnect grace.");
6969
+ }
6970
+ }
6943
6971
  for (const [who, reason] of departures) {
6944
6972
  const last = previous.get(who);
6945
6973
  const dropped = !saidBye.has(who) && (isUnannouncedDeparture(reason) || silent.has(who));
@@ -6955,6 +6983,9 @@ function createRoomEngine(options) {
6955
6983
  }
6956
6984
  departures.clear();
6957
6985
  liveRoster = list;
6986
+ for (const p of list) {
6987
+ if (!p.isLocal && (isGuestIdentity(p.identity) || userIdOfIdentity(p.identity) !== null)) liveness.expect(p.identity);
6988
+ }
6958
6989
  const localNow = list.find((p) => p.isLocal);
6959
6990
  if (localNow !== void 0 && !localNow.screenSharing && store.snapshot().share.state === "presenting") {
6960
6991
  store.patch({ share: NO_SHARE });
@@ -6975,7 +7006,7 @@ function createRoomEngine(options) {
6975
7006
  store.setParticipants(
6976
7007
  [...people.values()].map(({ entry }) => {
6977
7008
  const projected = projectParticipant(entry, joinedAt);
6978
- if (entry.reconnecting === true || !entry.isLocal && silent.has(entry.identity)) {
7009
+ if (entry.reconnecting === true || !entry.isLocal && silent.has(entry.identity) && !saidBye.has(entry.identity)) {
6979
7010
  return { ...projected, reconnecting: true, quality: "lost" };
6980
7011
  }
6981
7012
  const videoPaused = entry.isLocal ? store.snapshot().localNetwork.videoPaused : liveness.reported(entry.identity)?.vp === true;
@@ -7749,14 +7780,22 @@ function createLiveKitDriver(handlers, options = {}) {
7749
7780
  ...options.roomOptions
7750
7781
  });
7751
7782
  const reasonName = (reason) => reason === void 0 || reason === null ? null : module2.DisconnectReason?.[reason] ?? String(reason);
7752
- const roster = () => {
7783
+ const emitRoster = () => {
7784
+ rosterQueued = false;
7785
+ if (room !== created) return;
7753
7786
  const local = snapshotParticipant(created.localParticipant, true);
7754
7787
  const remotes = [...created.remoteParticipants.values()].map(
7755
7788
  (participant) => snapshotParticipant(participant, false)
7756
7789
  );
7757
7790
  handlers.participants([local, ...remotes]);
7758
7791
  };
7759
- projectRoster = roster;
7792
+ let rosterQueued = false;
7793
+ const roster = () => {
7794
+ if (rosterQueued) return;
7795
+ rosterQueued = true;
7796
+ queueMicrotask(emitRoster);
7797
+ };
7798
+ projectRoster = emitRoster;
7760
7799
  created.on(RoomEvent.TrackSubscribed, (track) => {
7761
7800
  if (track.kind !== Track.Kind.Audio || typeof document === "undefined") return;
7762
7801
  if (!remoteAudioPlayback) return;