@ai-matrx/meet 0.7.73 → 0.7.76

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
@@ -523,6 +523,12 @@ var MEET_ROUTES = {
523
523
  record: "/api/v1/meet/record",
524
524
  /** A host chooses what guests may read of ONE meeting (MRF-1). */
525
525
  recordAccess: "/api/v1/meet/record/access",
526
+ /**
527
+ * KEEP YOUR NOTES (2026-10-01): a guest who just created an account presents
528
+ * their kept pass in `x-meet-room-token` with their new session, and the
529
+ * meeting they attended becomes theirs to read. Idempotent; never a grant.
530
+ */
531
+ claim: "/api/v1/meet/claim",
526
532
  /**
527
533
  * Meet wave 1 (0.8): bring every invitee up to date after a write — sends the
528
534
  * invitation / update / cancellation emails with their `.ics` and re-queues
@@ -5829,7 +5835,7 @@ var import_format = require("@ai-matrx/kit/format");
5829
5835
  function activeWrapUpSummary(notes) {
5830
5836
  return notes.find((note) => note.role === "summary" && note.supersededBy === null) ?? null;
5831
5837
  }
5832
- var RESTRICTION_REMEDY = "The people in this meeting's organization can read it. Sign in with an account in that organization \u2014 following the link is enough to join a meeting, but not to read its record.";
5838
+ var RESTRICTION_REMEDY = "Open it from the meeting link in the browser you attended with, or ask the host to share it.";
5833
5839
  var PART_LABEL = {
5834
5840
  transcript: "The transcript of this meeting is not readable from this account.",
5835
5841
  notes: "The notes, decisions and action items are not readable from this account.",
@@ -6088,7 +6094,8 @@ function summarizeMeetingRecordRestrictions(restrictions) {
6088
6094
  }
6089
6095
  async function loadGuestMeetingRecord(args) {
6090
6096
  const { api, repository, meetingId, meeting, roomToken } = args;
6091
- if (roomToken === null) {
6097
+ const session = args.session === true;
6098
+ if (roomToken === null && !session) {
6092
6099
  return refusedBundle(
6093
6100
  meeting,
6094
6101
  "This meeting's record is only readable by the people who were in it.",
@@ -6101,9 +6108,9 @@ async function loadGuestMeetingRecord(args) {
6101
6108
  path: `${MEET_ROUTES.record}?meeting_id=${encodeURIComponent(meetingId)}`,
6102
6109
  method: "GET",
6103
6110
  // A GUEST HAS NO SESSION AND IS STILL A FIRST-CLASS READER (D6).
6104
- requireAuth: false,
6111
+ requireAuth: session,
6105
6112
  operation: "meet.record",
6106
- headers: { [ROOM_TOKEN_HEADER]: roomToken.token }
6113
+ headers: roomToken === null ? {} : { [ROOM_TOKEN_HEADER]: roomToken.token }
6107
6114
  });
6108
6115
  } catch (error) {
6109
6116
  return refusedBundle(
@@ -6832,7 +6839,24 @@ function useMeetingRecord(meeting) {
6832
6839
  meetingId,
6833
6840
  meeting,
6834
6841
  roomToken: tokens.remembered(roomName)
6835
- }) : loadMeetingRecord(repository, meetingId, meeting, { userId: readerId });
6842
+ }) : loadMeetingRecord(repository, meetingId, meeting, { userId: readerId }).then(
6843
+ (direct) => (
6844
+ // A SIGNED-IN OUTSIDER IS NOT A STRANGER (2026-10-01). The database
6845
+ // answers members and invitees; a person from another organization
6846
+ // the host admitted — or a guest who later made an account — reads
6847
+ // the guest share through the server, with their session as the pass.
6848
+ api !== null && direct.restrictions.some((part) => part.part === "notes") ? loadGuestMeetingRecord({
6849
+ api,
6850
+ repository,
6851
+ meetingId,
6852
+ meeting,
6853
+ roomToken: null,
6854
+ session: true
6855
+ }).then(
6856
+ (viaServer) => viaServer.restrictions.length < direct.restrictions.length ? viaServer : direct
6857
+ ) : direct
6858
+ )
6859
+ );
6836
6860
  void load.then((bundle) => {
6837
6861
  if (!live) return;
6838
6862
  setRecordReaderId(readerId);
@@ -8252,6 +8276,7 @@ function WhiteboardPanel({ onClose }) {
8252
8276
  function clock(ms2) {
8253
8277
  return (0, import_format3.formatDurationMs)(Math.ceil(ms2 / 1e3) * 1e3, { style: "clock" });
8254
8278
  }
8279
+ var BREAKOUT_EXPIRE_RETRY_MS = 5e3;
8255
8280
  function useNow(active) {
8256
8281
  const [now, setNow] = (0, import_react4.useState)(() => Date.now());
8257
8282
  (0, import_react4.useEffect)(() => {
@@ -8512,10 +8537,11 @@ function BreakoutBanner() {
8512
8537
  }, [moveAt, host, moveTo]);
8513
8538
  (0, import_react4.useEffect)(() => {
8514
8539
  if (open === null || remaining === null || remaining > 0) return;
8515
- if (expireAsked.current === open.id) return;
8516
- expireAsked.current = open.id;
8540
+ const asked = expireAsked.current;
8541
+ if (asked !== null && asked.id === open.id && now - asked.at < BREAKOUT_EXPIRE_RETRY_MS) return;
8542
+ expireAsked.current = { id: open.id, at: now };
8517
8543
  void act({ action: "breakout_expire" });
8518
- }, [open, remaining, act]);
8544
+ }, [open, remaining, act, now]);
8519
8545
  const broadcast = collab?.broadcast ?? null;
8520
8546
  const showBroadcast = broadcast !== null && broadcast.at !== dismissedBroadcast && open !== null;
8521
8547
  const room = open?.rooms.find((r) => r.id === breakoutRoomId) ?? null;
@@ -9823,38 +9849,40 @@ function EffectsSettings({ preview }) {
9823
9849
  }
9824
9850
  };
9825
9851
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__section", "aria-label": "Effects", children: [
9826
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__toggle", children: [
9852
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__check", children: [
9827
9853
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
9828
- "input",
9854
+ import_design_system.Checkbox,
9829
9855
  {
9830
- type: "checkbox",
9856
+ id: "mx-meet-noise",
9831
9857
  checked: effects.effects.noiseSuppression,
9832
- onChange: (event) => apply({ noiseSuppression: event.target.checked })
9858
+ onCheckedChange: (checked) => apply({ noiseSuppression: checked === true })
9833
9859
  }
9834
9860
  ),
9835
- "Noise suppression",
9836
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__hint", children: "Filters keyboards, fans and background chatter." })
9861
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__check-text", children: [
9862
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system.Label, { htmlFor: "mx-meet-noise", children: "Noise suppression" }),
9863
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__hint", children: "Filters keyboards, fans and background chatter." })
9864
+ ] })
9837
9865
  ] }),
9838
9866
  supported ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__field", children: [
9839
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: "Background" }),
9840
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__pills", role: "radiogroup", "aria-label": "Background", children: ["none", "blur", "image"].map((kind) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
9841
- "button",
9867
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system.Label, { children: "Background" }),
9868
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
9869
+ import_design_system.SegmentedControl,
9842
9870
  {
9843
- type: "button",
9844
- role: "radio",
9845
- "aria-checked": effects.effects.background === kind,
9846
- className: effects.effects.background === kind ? "mx-meet__pill mx-meet__pill--on" : "mx-meet__pill",
9847
- onClick: () => {
9871
+ value: effects.effects.background,
9872
+ onValueChange: (kind) => {
9848
9873
  if (kind === "image") {
9849
9874
  fileRef.current?.click();
9850
9875
  return;
9851
9876
  }
9852
9877
  apply({ background: kind });
9853
9878
  },
9854
- children: kind === "none" ? "None" : kind === "blur" ? "Blur" : "Picture\u2026"
9855
- },
9856
- kind
9857
- )) }),
9879
+ data: [
9880
+ { value: "none", label: "None" },
9881
+ { value: "blur", label: "Blur" },
9882
+ { value: "image", label: "Picture\u2026" }
9883
+ ]
9884
+ }
9885
+ ),
9858
9886
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
9859
9887
  "input",
9860
9888
  {
@@ -10238,10 +10266,10 @@ function PreJoinBody({
10238
10266
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__field-row", children: [
10239
10267
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "audiooutput", label: "Speaker" }),
10240
10268
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
10241
- "button",
10269
+ import_design_system.Button,
10242
10270
  {
10243
10271
  type: "button",
10244
- className: "mx-meet__chip",
10272
+ variant: "outline",
10245
10273
  disabled: speakerTesting,
10246
10274
  onClick: () => {
10247
10275
  setSpeakerTesting(true);
@@ -10250,7 +10278,7 @@ function PreJoinBody({
10250
10278
  );
10251
10279
  },
10252
10280
  children: [
10253
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpeakerIcon, { width: 14, height: 14 }),
10281
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpeakerIcon, {}),
10254
10282
  " ",
10255
10283
  speakerTesting ? "Playing\u2026" : "Test"
10256
10284
  ]
@@ -10259,35 +10287,36 @@ function PreJoinBody({
10259
10287
  ] }),
10260
10288
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "videoinput", label: "Camera" }),
10261
10289
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(EffectsSettings, { preview: preview.preview }),
10262
- recording.consentNotice !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__consent", children: recording.consentNotice }) : null,
10290
+ recording.consentNotice !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system.Alert, { variant: "info", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system.AlertDescription, { children: recording.consentNotice }) }) : null,
10263
10291
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__prejoin-actions", children: [
10264
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__toggle", children: [
10292
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__check", children: [
10265
10293
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
10266
- "input",
10294
+ import_design_system.Checkbox,
10267
10295
  {
10268
- type: "checkbox",
10296
+ id: "mx-meet-join-video",
10269
10297
  checked: mode === "video",
10270
- onChange: (event) => setMode(event.target.checked ? "video" : "audio")
10298
+ onCheckedChange: (checked) => setMode(checked === true ? "video" : "audio")
10271
10299
  }
10272
10300
  ),
10273
- "Join with video"
10301
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system.Label, { htmlFor: "mx-meet-join-video", children: "Join with video" })
10274
10302
  ] }),
10275
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__toggle", children: [
10303
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__check", children: [
10276
10304
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
10277
- "input",
10305
+ import_design_system.Checkbox,
10278
10306
  {
10279
- type: "checkbox",
10307
+ id: "mx-meet-join-mic",
10280
10308
  checked: microphone,
10281
- onChange: (event) => setMicrophone(event.target.checked)
10309
+ onCheckedChange: (checked) => setMicrophone(checked === true)
10282
10310
  }
10283
10311
  ),
10284
- "Join with microphone"
10312
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system.Label, { htmlFor: "mx-meet-join-mic", children: "Join with microphone" })
10285
10313
  ] }),
10286
10314
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
10287
- "button",
10315
+ import_design_system.Button,
10288
10316
  {
10289
10317
  type: "button",
10290
- className: "mx-meet__primary",
10318
+ className: "mx-meet__join",
10319
+ disabled: joining,
10291
10320
  onClick: () => {
10292
10321
  setJoining(true);
10293
10322
  preview.release();
@@ -10360,18 +10389,24 @@ function DevicePicker({
10360
10389
  const devices = useDeviceSnapshot();
10361
10390
  const list = devices?.devices[kind] ?? [];
10362
10391
  if (list.length === 0) return null;
10363
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__field", children: [
10364
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: label }),
10365
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
10366
- "select",
10392
+ const triggerId = `mx-meet-device-${kind}`;
10393
+ const valueOf = (deviceId2) => deviceId2.length > 0 ? deviceId2 : "default";
10394
+ const current = devices?.selected[kind] ?? host.devices.resolve(kind) ?? "";
10395
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__field", children: [
10396
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system.Label, { htmlFor: triggerId, children: label }),
10397
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
10398
+ import_design_system.Select,
10367
10399
  {
10368
- className: "mx-meet__select",
10369
- value: devices?.selected[kind] ?? host.devices.resolve(kind) ?? "",
10370
- onChange: (event) => {
10371
- if (onPick !== void 0) onPick(kind, event.target.value);
10372
- else host.devices.select(kind, event.target.value);
10400
+ ...current.length > 0 ? { value: valueOf(current) } : {},
10401
+ onValueChange: (value) => {
10402
+ const deviceId2 = list.find((device) => valueOf(device.deviceId) === value)?.deviceId ?? value;
10403
+ if (onPick !== void 0) onPick(kind, deviceId2);
10404
+ else host.devices.select(kind, deviceId2);
10373
10405
  },
10374
- children: list.map((device) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: device.deviceId, children: device.label.length > 0 ? device.label : `${label} (name hidden)` }, device.deviceId))
10406
+ children: [
10407
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system.SelectTrigger, { id: triggerId, "aria-label": label, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system.SelectValue, { placeholder: label }) }),
10408
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system.SelectContent, { children: list.map((device) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system.SelectItem, { value: valueOf(device.deviceId), children: device.label.length > 0 ? device.label : `${label} (name hidden)` }, device.deviceId || "default")) })
10409
+ ]
10375
10410
  }
10376
10411
  )
10377
10412
  ] });