@sparkelf/dsh-group-chat 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -125,6 +125,10 @@ window.__ModuleLoader__.load({
125
125
  const suffix = path === void 0 || path.length === 0 ? "" : `?path=${encodeURIComponent(path)}`;
126
126
  return call(`/directories${suffix}`);
127
127
  };
128
+ const listEvents = (roomId, cursor) => {
129
+ const suffix = cursor === void 0 ? "" : `?cursor=${encodeURIComponent(cursor)}`;
130
+ return call(`/rooms/${encodeURIComponent(roomId)}/events${suffix}`);
131
+ };
128
132
  /**
129
133
  * Create a room.
130
134
  *
@@ -233,6 +237,30 @@ window.__ModuleLoader__.load({
233
237
  * pre-empted here.
234
238
  */
235
239
  const dissolveRoom = (roomId) => call(`/rooms/${encodeURIComponent(roomId)}`, { method: "DELETE" });
240
+ /**
241
+ * Searches message text across the rooms this account can read.
242
+ *
243
+ * The room server owns the visibility rule; this only passes the words. An empty query is not
244
+ * sent at all — every message would match it.
245
+ */
246
+ const searchMessages = (query) => {
247
+ const trimmed = query.trim();
248
+ if (trimmed.length === 0) return Promise.resolve([]);
249
+ return call(`/rooms/messages/search?query=${encodeURIComponent(trimmed)}`);
250
+ };
251
+ /**
252
+ * Registers a pending reply with the host.
253
+ *
254
+ * The message itself is submitted by the official composer, which this plugin neither wraps nor
255
+ * intercepts, so the quote travels beside it rather than inside it: the host attaches it to the
256
+ * next message this member sends in the room and then forgets it.
257
+ */
258
+ const registerQuote = (roomId, quote) => call(`/rooms/${encodeURIComponent(roomId)}/quote`, {
259
+ method: "POST",
260
+ body: JSON.stringify(quote)
261
+ });
262
+ /** Drops a pending reply that will not be sent. */
263
+ const clearQuote = (roomId) => call(`/rooms/${encodeURIComponent(roomId)}/quote`, { method: "DELETE" });
236
264
  //#endregion
237
265
  //#region src/client/rows.ts
238
266
  /**
@@ -474,21 +502,21 @@ window.__ModuleLoader__.load({
474
502
  const announcementMissing = (error) => error instanceof RoomError && (error.status === 404 || error.status === 405 || error.status === 501);
475
503
  //#endregion
476
504
  //#region \0dsh-css:/root/projects/dsh-plugins-plus/packages/group-chat/src/client/Avatar.module.css.mjs
477
- const css$8 = ".Ohch6W_avatar{letter-spacing:.02em;color:#fff;background:var(--dsw-static-blue-600,#2563eb);user-select:none;border-radius:50%;flex:none;justify-content:center;align-items:center;font-weight:600;display:inline-flex;overflow:hidden}.Ohch6W_md{width:30px;height:30px;font-size:12px;line-height:30px}.Ohch6W_sm{width:24px;height:24px;font-size:10px;line-height:24px}.Ohch6W_stack{flex:none;display:inline-flex;position:relative}.Ohch6W_over{background:0 0;position:absolute;inset:0}img.Ohch6W_avatar{object-fit:cover;background:0 0}";
478
- const tagId$8 = "@sparkelf/dsh-group-chat/Avatar.module.css";
479
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$8) + "]") === null) {
505
+ const css$9 = ".Ohch6W_avatar{letter-spacing:.02em;color:#fff;background:var(--dsw-static-blue-600,#2563eb);user-select:none;border-radius:50%;flex:none;justify-content:center;align-items:center;font-weight:600;display:inline-flex;overflow:hidden}.Ohch6W_md{width:30px;height:30px;font-size:12px;line-height:30px}.Ohch6W_sm{width:24px;height:24px;font-size:10px;line-height:24px}.Ohch6W_stack{flex:none;display:inline-flex;position:relative}.Ohch6W_over{background:0 0;position:absolute;inset:0}img.Ohch6W_avatar{object-fit:cover;background:0 0}";
506
+ const tagId$9 = "@sparkelf/dsh-group-chat/Avatar.module.css";
507
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$9) + "]") === null) {
480
508
  const tag = document.createElement("style");
481
509
  tag.dataset.plugin = "@sparkelf/dsh-group-chat";
482
- tag.dataset.pluginCss = tagId$8;
483
- tag.textContent = css$8;
510
+ tag.dataset.pluginCss = tagId$9;
511
+ tag.textContent = css$9;
484
512
  document.head.appendChild(tag);
485
513
  }
486
514
  var Avatar_module_css_default = {
487
515
  "sm": "Ohch6W_sm",
488
- "over": "Ohch6W_over",
489
- "md": "Ohch6W_md",
490
516
  "avatar": "Ohch6W_avatar",
491
- "stack": "Ohch6W_stack"
517
+ "stack": "Ohch6W_stack",
518
+ "over": "Ohch6W_over",
519
+ "md": "Ohch6W_md"
492
520
  };
493
521
  //#endregion
494
522
  //#region src/client/Avatar.tsx
@@ -518,23 +546,23 @@ window.__ModuleLoader__.load({
518
546
  };
519
547
  //#endregion
520
548
  //#region \0dsh-css:/root/projects/dsh-plugins-plus/packages/group-chat/src/client/Picker.module.css.mjs
521
- const css$7 = ".sKjJ-a_box{flex-direction:column;min-width:0;display:flex;position:relative}.sKjJ-a_list{z-index:10;border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-base,var(--dsw-alias-interactive-bg-hover));max-height:240px;padding:4px;position:absolute;top:calc(100% + 4px);left:0;right:0;overflow-y:auto;box-shadow:0 8px 24px #0000003d}.sKjJ-a_row,.sKjJ-a_rowActive{border-radius:var(--dsw-radius-sm);width:100%;color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:6px 8px;font-size:13px;line-height:18px;display:flex}.sKjJ-a_rowActive{background:var(--dsw-alias-interactive-bg-hover)}.sKjJ-a_label{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}.sKjJ-a_secondary{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px}.sKjJ-a_note{color:var(--dsw-alias-label-tertiary);margin:6px 8px;font-size:12px;line-height:17px}";
522
- const tagId$7 = "@sparkelf/dsh-group-chat/Picker.module.css";
523
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$7) + "]") === null) {
549
+ const css$8 = ".sKjJ-a_box{flex-direction:column;min-width:0;display:flex;position:relative}.sKjJ-a_list{z-index:10;border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-base,var(--dsw-alias-interactive-bg-hover));max-height:240px;padding:4px;position:absolute;top:calc(100% + 4px);left:0;right:0;overflow-y:auto;box-shadow:0 8px 24px #0000003d}.sKjJ-a_row,.sKjJ-a_rowActive{border-radius:var(--dsw-radius-sm);width:100%;color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:6px 8px;font-size:13px;line-height:18px;display:flex}.sKjJ-a_rowActive{background:var(--dsw-alias-interactive-bg-hover)}.sKjJ-a_label{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}.sKjJ-a_secondary{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px}.sKjJ-a_note{color:var(--dsw-alias-label-tertiary);margin:6px 8px;font-size:12px;line-height:17px}";
550
+ const tagId$8 = "@sparkelf/dsh-group-chat/Picker.module.css";
551
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$8) + "]") === null) {
524
552
  const tag = document.createElement("style");
525
553
  tag.dataset.plugin = "@sparkelf/dsh-group-chat";
526
- tag.dataset.pluginCss = tagId$7;
527
- tag.textContent = css$7;
554
+ tag.dataset.pluginCss = tagId$8;
555
+ tag.textContent = css$8;
528
556
  document.head.appendChild(tag);
529
557
  }
530
558
  var Picker_module_css_default = {
531
- "note": "sKjJ-a_note",
532
- "secondary": "sKjJ-a_secondary",
533
- "list": "sKjJ-a_list",
534
- "row": "sKjJ-a_row",
535
559
  "box": "sKjJ-a_box",
536
560
  "rowActive": "sKjJ-a_rowActive",
537
- "label": "sKjJ-a_label"
561
+ "row": "sKjJ-a_row",
562
+ "secondary": "sKjJ-a_secondary",
563
+ "note": "sKjJ-a_note",
564
+ "label": "sKjJ-a_label",
565
+ "list": "sKjJ-a_list"
538
566
  };
539
567
  //#endregion
540
568
  //#region src/client/Picker.tsx
@@ -697,21 +725,21 @@ window.__ModuleLoader__.load({
697
725
  };
698
726
  //#endregion
699
727
  //#region \0dsh-css:/root/projects/dsh-plugins-plus/packages/group-chat/src/client/PresetSelect.module.css.mjs
700
- const css$6 = ".xjnmxG_trigger{border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm);width:100%;color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer;background:0 0;align-items:center;gap:6px;padding:6px 10px;font-size:13px;line-height:18px;display:flex}.xjnmxG_trigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.xjnmxG_triggerLabel{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}.xjnmxG_trigger:after{border-right:1.5px solid var(--dsw-alias-label-tertiary);border-bottom:1.5px solid var(--dsw-alias-label-tertiary);content:\"\";flex:none;width:6px;height:6px;margin-left:2px;transform:translateY(-1px)rotate(45deg)}.xjnmxG_row{flex-direction:column;gap:2px;min-width:0;display:flex}.xjnmxG_name{color:var(--dsw-alias-label-primary);font-size:13px;line-height:18px}.xjnmxG_description{color:var(--dsw-alias-label-tertiary);white-space:normal;font-size:12px;line-height:17px}";
701
- const tagId$6 = "@sparkelf/dsh-group-chat/PresetSelect.module.css";
702
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$6) + "]") === null) {
728
+ const css$7 = ".xjnmxG_trigger{border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm);width:100%;color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer;background:0 0;align-items:center;gap:6px;padding:6px 10px;font-size:13px;line-height:18px;display:flex}.xjnmxG_trigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.xjnmxG_triggerLabel{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}.xjnmxG_trigger:after{border-right:1.5px solid var(--dsw-alias-label-tertiary);border-bottom:1.5px solid var(--dsw-alias-label-tertiary);content:\"\";flex:none;width:6px;height:6px;margin-left:2px;transform:translateY(-1px)rotate(45deg)}.xjnmxG_row{flex-direction:column;gap:2px;min-width:0;display:flex}.xjnmxG_name{color:var(--dsw-alias-label-primary);font-size:13px;line-height:18px}.xjnmxG_description{color:var(--dsw-alias-label-tertiary);white-space:normal;font-size:12px;line-height:17px}";
729
+ const tagId$7 = "@sparkelf/dsh-group-chat/PresetSelect.module.css";
730
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$7) + "]") === null) {
703
731
  const tag = document.createElement("style");
704
732
  tag.dataset.plugin = "@sparkelf/dsh-group-chat";
705
- tag.dataset.pluginCss = tagId$6;
706
- tag.textContent = css$6;
733
+ tag.dataset.pluginCss = tagId$7;
734
+ tag.textContent = css$7;
707
735
  document.head.appendChild(tag);
708
736
  }
709
737
  var PresetSelect_module_css_default = {
710
- "description": "xjnmxG_description",
711
- "triggerLabel": "xjnmxG_triggerLabel",
712
738
  "row": "xjnmxG_row",
739
+ "description": "xjnmxG_description",
740
+ "trigger": "xjnmxG_trigger",
713
741
  "name": "xjnmxG_name",
714
- "trigger": "xjnmxG_trigger"
742
+ "triggerLabel": "xjnmxG_triggerLabel"
715
743
  };
716
744
  //#endregion
717
745
  //#region src/client/PresetSelect.tsx
@@ -959,33 +987,33 @@ window.__ModuleLoader__.load({
959
987
  };
960
988
  //#endregion
961
989
  //#region \0dsh-css:/root/projects/dsh-plugins-plus/packages/group-chat/src/client/CreateRoomDialog.module.css.mjs
962
- const css$5 = ".Z3w8WW_body{flex-direction:column;gap:14px;min-width:0;display:flex}.Z3w8WW_field{flex-direction:column;gap:5px;min-width:0;display:flex}.Z3w8WW_label{color:var(--dsw-alias-label-primary);font-size:13px;line-height:18px}.Z3w8WW_hint{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:17px}.Z3w8WW_warn{border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-warning,#d299221f);color:var(--dsw-alias-state-warning-primary,#d29922);padding:6px 8px;font-size:12px;line-height:17px;display:block}.Z3w8WW_switches{border-top:1px solid var(--dsw-alias-border-l3);flex-direction:column;gap:8px;padding:10px 0 0;display:flex}.Z3w8WW_triggerExtra{flex-wrap:wrap;gap:6px;padding-left:0;display:flex}.Z3w8WW_pill,.Z3w8WW_pillActive{border:1px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border-radius:999px;padding:4px 10px;font-size:12px}.Z3w8WW_pillActive{border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-label-primary)}.Z3w8WW_notice{border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-2,#80808014);color:var(--dsw-alias-label-secondary);margin:0;padding:8px 10px;font-size:12px;line-height:17px}.Z3w8WW_error{color:var(--dsw-alias-state-error-primary,#f85149);margin:0;font-size:12px;line-height:17px}.Z3w8WW_footer{justify-content:flex-end;gap:8px;display:flex}.Z3w8WW_policyRow{flex-direction:column;gap:5px;display:flex}.Z3w8WW_memberList{flex-direction:column;gap:2px;margin:0;padding:0;list-style:none;display:flex}.Z3w8WW_memberRow{border-radius:var(--dsw-radius-sm);align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.Z3w8WW_memberRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.Z3w8WW_memberName{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.Z3w8WW_memberBadge{background:var(--dsw-alias-bg-layer-2,#8080801f);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:0 6px;font-size:11px;line-height:16px}";
963
- const tagId$5 = "@sparkelf/dsh-group-chat/CreateRoomDialog.module.css";
964
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$5) + "]") === null) {
990
+ const css$6 = ".Z3w8WW_body{flex-direction:column;gap:14px;min-width:0;display:flex}.Z3w8WW_field{flex-direction:column;gap:5px;min-width:0;display:flex}.Z3w8WW_label{color:var(--dsw-alias-label-primary);font-size:13px;line-height:18px}.Z3w8WW_hint{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:17px}.Z3w8WW_warn{border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-warning,#d299221f);color:var(--dsw-alias-state-warning-primary,#d29922);padding:6px 8px;font-size:12px;line-height:17px;display:block}.Z3w8WW_switches{border-top:1px solid var(--dsw-alias-border-l3);flex-direction:column;gap:8px;padding:10px 0 0;display:flex}.Z3w8WW_triggerExtra{flex-wrap:wrap;gap:6px;padding-left:0;display:flex}.Z3w8WW_pill,.Z3w8WW_pillActive{border:1px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border-radius:999px;padding:4px 10px;font-size:12px}.Z3w8WW_pillActive{border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-label-primary)}.Z3w8WW_notice{border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-2,#80808014);color:var(--dsw-alias-label-secondary);margin:0;padding:8px 10px;font-size:12px;line-height:17px}.Z3w8WW_error{color:var(--dsw-alias-state-error-primary,#f85149);margin:0;font-size:12px;line-height:17px}.Z3w8WW_footer{justify-content:flex-end;gap:8px;display:flex}.Z3w8WW_policyRow{flex-direction:column;gap:5px;display:flex}.Z3w8WW_memberList{flex-direction:column;gap:2px;margin:0;padding:0;list-style:none;display:flex}.Z3w8WW_memberRow{border-radius:var(--dsw-radius-sm);align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.Z3w8WW_memberRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.Z3w8WW_memberName{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.Z3w8WW_memberBadge{background:var(--dsw-alias-bg-layer-2,#8080801f);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:0 6px;font-size:11px;line-height:16px}";
991
+ const tagId$6 = "@sparkelf/dsh-group-chat/CreateRoomDialog.module.css";
992
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$6) + "]") === null) {
965
993
  const tag = document.createElement("style");
966
994
  tag.dataset.plugin = "@sparkelf/dsh-group-chat";
967
- tag.dataset.pluginCss = tagId$5;
968
- tag.textContent = css$5;
995
+ tag.dataset.pluginCss = tagId$6;
996
+ tag.textContent = css$6;
969
997
  document.head.appendChild(tag);
970
998
  }
971
999
  var CreateRoomDialog_module_css_default = {
972
- "label": "Z3w8WW_label",
973
- "pillActive": "Z3w8WW_pillActive",
974
- "notice": "Z3w8WW_notice",
975
- "hint": "Z3w8WW_hint",
976
- "policyRow": "Z3w8WW_policyRow",
977
1000
  "pill": "Z3w8WW_pill",
1001
+ "footer": "Z3w8WW_footer",
1002
+ "triggerExtra": "Z3w8WW_triggerExtra",
1003
+ "policyRow": "Z3w8WW_policyRow",
1004
+ "error": "Z3w8WW_error",
1005
+ "switches": "Z3w8WW_switches",
1006
+ "hint": "Z3w8WW_hint",
978
1007
  "field": "Z3w8WW_field",
979
- "memberList": "Z3w8WW_memberList",
1008
+ "pillActive": "Z3w8WW_pillActive",
980
1009
  "memberName": "Z3w8WW_memberName",
981
- "memberBadge": "Z3w8WW_memberBadge",
982
- "warn": "Z3w8WW_warn",
983
- "error": "Z3w8WW_error",
984
- "triggerExtra": "Z3w8WW_triggerExtra",
985
- "memberRow": "Z3w8WW_memberRow",
1010
+ "label": "Z3w8WW_label",
986
1011
  "body": "Z3w8WW_body",
987
- "footer": "Z3w8WW_footer",
988
- "switches": "Z3w8WW_switches"
1012
+ "memberRow": "Z3w8WW_memberRow",
1013
+ "warn": "Z3w8WW_warn",
1014
+ "memberList": "Z3w8WW_memberList",
1015
+ "memberBadge": "Z3w8WW_memberBadge",
1016
+ "notice": "Z3w8WW_notice"
989
1017
  };
990
1018
  //#endregion
991
1019
  //#region src/client/CreateRoomDialog.tsx
@@ -1242,38 +1270,38 @@ window.__ModuleLoader__.load({
1242
1270
  }
1243
1271
  //#endregion
1244
1272
  //#region \0dsh-css:/root/projects/dsh-plugins-plus/packages/group-chat/src/client/InviteDialog.module.css.mjs
1245
- const css$4 = ".r4uCba_dialog.r4uCba_dialog{width:min(760px,100%);max-height:100%}.r4uCba_content{overscroll-behavior:contain;min-height:0;overflow-y:auto}.r4uCba_searchRow{align-items:center;gap:8px;min-width:0;display:flex;position:relative}.r4uCba_search{flex:1;min-width:0}.r4uCba_spinner{color:var(--dsw-alias-label-tertiary);flex:none;animation:.9s linear infinite r4uCba_inviteSpin}@keyframes r4uCba_inviteSpin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.r4uCba_spinner{animation:none}}.r4uCba_visuallyHidden{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.r4uCba_field{flex-direction:column;gap:5px;min-width:0;display:flex}.r4uCba_chips{flex-wrap:wrap;gap:6px;margin:0;padding:0;list-style:none;display:flex}.r4uCba_chip{border:1px solid var(--dsw-alias-border-l3);border-radius:999px;align-items:center;gap:6px;max-width:100%;padding:3px 6px 3px 3px;font-size:12px;line-height:18px;display:inline-flex}.r4uCba_chipName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.r4uCba_chipRemove{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;flex:none;padding:0 2px;font-size:14px;line-height:14px}.r4uCba_chipRemove:hover{color:var(--dsw-alias-label-primary)}.r4uCba_chipRemove:focus-visible{outline:var(--dsw-focus-ring-width,2px) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px;border-radius:var(--dsw-radius-sm)}.r4uCba_list{scrollbar-gutter:stable;border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);max-height:min(46vh,420px);margin:0;padding:4px;list-style:none;overflow-y:auto}.r4uCba_list>li+li{margin-top:2px}.r4uCba_row,.r4uCba_rowSelected{box-sizing:border-box;border-radius:var(--dsw-radius-sm);width:100%;min-height:38px;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:1px solid #0000;align-items:center;gap:8px;padding:5px 8px;font-size:13px;line-height:18px;display:flex}.r4uCba_row:hover{background:var(--dsw-alias-interactive-bg-hover)}.r4uCba_rowSelected{border-color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-interactive-bg-active)}.r4uCba_rowSelected:hover{background:var(--dsw-alias-interactive-bg-hover-accent)}.r4uCba_row:focus-visible,.r4uCba_rowSelected:focus-visible{outline:var(--dsw-focus-ring-width,2px) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:-2px}.r4uCba_rowName{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}.r4uCba_rowHandle{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px}.r4uCba_check,.r4uCba_checkHidden{width:14px;color:var(--dsw-alias-state-business-primary);flex:none;justify-content:center;align-items:center;display:inline-flex}.r4uCba_checkHidden{visibility:hidden}.r4uCba_note{color:var(--dsw-alias-label-tertiary);margin:0;padding:14px 10px;font-size:12px;line-height:17px}.r4uCba_errorRow{align-items:center;gap:8px;min-width:0;display:flex}.r4uCba_errorRow>span{flex:1;min-width:0}.r4uCba_error{color:var(--dsw-alias-state-error-primary,#f85149);margin:0;font-size:12px;line-height:17px}";
1246
- const tagId$4 = "@sparkelf/dsh-group-chat/InviteDialog.module.css";
1247
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
1273
+ const css$5 = ".r4uCba_dialog.r4uCba_dialog{width:min(760px,100%);max-height:100%}.r4uCba_content{overscroll-behavior:contain;min-height:0;overflow-y:auto}.r4uCba_searchRow{align-items:center;gap:8px;min-width:0;display:flex;position:relative}.r4uCba_search{flex:1;min-width:0}.r4uCba_spinner{color:var(--dsw-alias-label-tertiary);flex:none;animation:.9s linear infinite r4uCba_inviteSpin}@keyframes r4uCba_inviteSpin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.r4uCba_spinner{animation:none}}.r4uCba_visuallyHidden{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.r4uCba_field{flex-direction:column;gap:5px;min-width:0;display:flex}.r4uCba_chips{flex-wrap:wrap;gap:6px;margin:0;padding:0;list-style:none;display:flex}.r4uCba_chip{border:1px solid var(--dsw-alias-border-l3);border-radius:999px;align-items:center;gap:6px;max-width:100%;padding:3px 6px 3px 3px;font-size:12px;line-height:18px;display:inline-flex}.r4uCba_chipName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.r4uCba_chipRemove{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;flex:none;padding:0 2px;font-size:14px;line-height:14px}.r4uCba_chipRemove:hover{color:var(--dsw-alias-label-primary)}.r4uCba_chipRemove:focus-visible{outline:var(--dsw-focus-ring-width,2px) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px;border-radius:var(--dsw-radius-sm)}.r4uCba_list{scrollbar-gutter:stable;border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);max-height:min(46vh,420px);margin:0;padding:4px;list-style:none;overflow-y:auto}.r4uCba_list>li+li{margin-top:2px}.r4uCba_row,.r4uCba_rowSelected{box-sizing:border-box;border-radius:var(--dsw-radius-sm);width:100%;min-height:38px;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:1px solid #0000;align-items:center;gap:8px;padding:5px 8px;font-size:13px;line-height:18px;display:flex}.r4uCba_row:hover{background:var(--dsw-alias-interactive-bg-hover)}.r4uCba_rowSelected{border-color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-interactive-bg-active)}.r4uCba_rowSelected:hover{background:var(--dsw-alias-interactive-bg-hover-accent)}.r4uCba_row:focus-visible,.r4uCba_rowSelected:focus-visible{outline:var(--dsw-focus-ring-width,2px) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:-2px}.r4uCba_rowName{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}.r4uCba_rowHandle{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px}.r4uCba_check,.r4uCba_checkHidden{width:14px;color:var(--dsw-alias-state-business-primary);flex:none;justify-content:center;align-items:center;display:inline-flex}.r4uCba_checkHidden{visibility:hidden}.r4uCba_note{color:var(--dsw-alias-label-tertiary);margin:0;padding:14px 10px;font-size:12px;line-height:17px}.r4uCba_errorRow{align-items:center;gap:8px;min-width:0;display:flex}.r4uCba_errorRow>span{flex:1;min-width:0}.r4uCba_error{color:var(--dsw-alias-state-error-primary,#f85149);margin:0;font-size:12px;line-height:17px}";
1274
+ const tagId$5 = "@sparkelf/dsh-group-chat/InviteDialog.module.css";
1275
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$5) + "]") === null) {
1248
1276
  const tag = document.createElement("style");
1249
1277
  tag.dataset.plugin = "@sparkelf/dsh-group-chat";
1250
- tag.dataset.pluginCss = tagId$4;
1251
- tag.textContent = css$4;
1278
+ tag.dataset.pluginCss = tagId$5;
1279
+ tag.textContent = css$5;
1252
1280
  document.head.appendChild(tag);
1253
1281
  }
1254
1282
  var InviteDialog_module_css_default = {
1283
+ "searchRow": "r4uCba_searchRow",
1284
+ "note": "r4uCba_note",
1285
+ "chip": "r4uCba_chip",
1286
+ "spinner": "r4uCba_spinner",
1287
+ "list": "r4uCba_list",
1288
+ "chipRemove": "r4uCba_chipRemove",
1289
+ "content": "r4uCba_content",
1255
1290
  "inviteSpin": "r4uCba_inviteSpin",
1256
- "rowName": "r4uCba_rowName",
1257
1291
  "search": "r4uCba_search",
1258
- "rowSelected": "r4uCba_rowSelected",
1259
- "note": "r4uCba_note",
1260
1292
  "chipName": "r4uCba_chipName",
1261
- "spinner": "r4uCba_spinner",
1293
+ "chips": "r4uCba_chips",
1294
+ "field": "r4uCba_field",
1295
+ "dialog": "r4uCba_dialog",
1262
1296
  "errorRow": "r4uCba_errorRow",
1263
1297
  "rowHandle": "r4uCba_rowHandle",
1264
- "error": "r4uCba_error",
1265
- "dialog": "r4uCba_dialog",
1298
+ "rowSelected": "r4uCba_rowSelected",
1266
1299
  "check": "r4uCba_check",
1267
- "chip": "r4uCba_chip",
1268
- "checkHidden": "r4uCba_checkHidden",
1269
- "chipRemove": "r4uCba_chipRemove",
1270
1300
  "row": "r4uCba_row",
1271
- "list": "r4uCba_list",
1301
+ "checkHidden": "r4uCba_checkHidden",
1272
1302
  "visuallyHidden": "r4uCba_visuallyHidden",
1273
- "content": "r4uCba_content",
1274
- "searchRow": "r4uCba_searchRow",
1275
- "field": "r4uCba_field",
1276
- "chips": "r4uCba_chips"
1303
+ "rowName": "r4uCba_rowName",
1304
+ "error": "r4uCba_error"
1277
1305
  };
1278
1306
  //#endregion
1279
1307
  //#region src/client/RoomDialogs.tsx
@@ -1880,68 +1908,76 @@ window.__ModuleLoader__.load({
1880
1908
  }
1881
1909
  //#endregion
1882
1910
  //#region \0dsh-css:/root/projects/dsh-plugins-plus/packages/group-chat/src/client/SidebarRooms.module.css.mjs
1883
- const css$3 = ".s0QgKq_root{--dsh-session-list-edge-inset:var(--dsh-sidebar-inline-padding,12px);--dsh-session-list-scrollbar-width:5px;--dsh-session-list-scrollbar-offset:2px;box-sizing:border-box;flex-direction:column;flex:auto;width:100%;min-width:0;min-height:0;max-height:20vh;display:flex;position:relative}.s0QgKq_resizer{z-index:1;cursor:row-resize;touch-action:none;background:0 0;height:6px;position:absolute;top:-3px;left:0;right:0}.s0QgKq_resizer:after{content:\"\";background:var(--dsw-alias-border-l1,var(--dsw-alias-separator-primary));opacity:0;border-radius:1px;height:1px;transition:opacity .12s;position:absolute;top:3px;left:8px;right:8px}.s0QgKq_root:hover .s0QgKq_resizer:after,.s0QgKq_resizer:focus-visible:after{opacity:1}.s0QgKq_resizer:focus-visible{outline:none}.s0QgKq_resizer:focus-visible:after{background:var(--dsw-alias-brand-primary,var(--dsw-alias-label-primary));height:2px}.s0QgKq_sectionHeader{box-sizing:border-box;border-radius:var(--dsw-radius-md);height:36px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:flex-end;align-items:center;gap:4px;margin-bottom:4px;margin-right:-4px;padding-left:4px;display:flex;overflow:hidden}.s0QgKq_sectionLabel{white-space:nowrap;flex:none;min-width:0;max-width:45%;line-height:20px;overflow:hidden}.s0QgKq_searchSlot{box-sizing:border-box;flex:1;align-items:center;min-width:0;max-width:28px;margin-left:auto;padding-left:0;display:flex}.s0QgKq_searchSlotExpanded{box-sizing:border-box;flex:1;align-items:center;min-width:0;max-width:100%;margin-left:auto;display:flex}.s0QgKq_search,.s0QgKq_searchExpanded{box-sizing:border-box;border-radius:var(--dsw-radius-sm);width:100%;height:28px;color:var(--dsw-alias-label-secondary);cursor:text;background:0 0;border:none;flex:none;align-items:center;margin:0;padding:0;display:flex;overflow:hidden}.s0QgKq_searchExpanded{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);width:calc(100% + 4px);height:30px;color:var(--dsw-alias-label-caption);margin-inline:-2px;padding:0 4px 0 0}.s0QgKq_iconButton{border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.s0QgKq_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_iconButton:focus-visible,.s0QgKq_searchButton:focus-visible,.s0QgKq_clearButton:focus-visible{outline:var(--dsw-focus-ring-width,2px) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:-2px}.s0QgKq_searchButton{border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:inherit;cursor:pointer;background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.s0QgKq_searchExpanded .s0QgKq_searchButton{width:28px;height:30px}.s0QgKq_searchButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_searchExpanded .s0QgKq_searchButton:hover{background:0 0}.s0QgKq_searchInput{width:0;min-width:0;color:var(--dsw-alias-label-primary);opacity:0;pointer-events:none;transition:opacity .12s var(--ds-ease-in-out);background:0 0;border:none;outline:none;flex:1;padding:0;font-size:13px;line-height:18px}.s0QgKq_searchExpanded .s0QgKq_searchInput{opacity:1;pointer-events:auto;margin-left:-2px}.s0QgKq_searchInput::placeholder{color:var(--dsw-alias-label-tertiary)}.s0QgKq_clearButton{border-radius:var(--dsw-radius-sm);width:24px;height:24px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.s0QgKq_clearButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_headerActions{flex:none;align-items:center;gap:4px;display:flex}.s0QgKq_viewWrap{display:flex;position:relative}.s0QgKq_listArea{min-height:0;margin-left:-4px;margin-right:calc(-1 * var(--dsh-session-list-edge-inset));flex-direction:column;flex:1;padding-left:4px;display:flex;position:relative}.s0QgKq_list{min-height:0;max-height:100%;margin-left:-4px;margin-right:var(--dsh-session-list-scrollbar-offset);padding-left:4px;padding-right:calc(var(--dsh-session-list-edge-inset) - var(--dsh-session-list-scrollbar-width) - var(--dsh-session-list-scrollbar-offset));scrollbar-gutter:stable;padding-bottom:8px;overflow-y:auto}.s0QgKq_flatList{margin:0;padding:0;list-style:none}.s0QgKq_flatList>*+*{margin-top:2px}.s0QgKq_sessionRow,.s0QgKq_sessionRowSelected{box-sizing:border-box;border-radius:var(--dsw-radius-sm);width:100%;height:32px;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:0 8px;font-size:14px;display:flex}.s0QgKq_sessionRow:hover,.s0QgKq_sessionRowSelected{background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_rowIcon{width:16px;color:var(--dsw-alias-label-secondary);flex:none;justify-content:center;align-items:center;display:flex}.s0QgKq_title{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.s0QgKq_time{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;font-size:12px;line-height:17px}.s0QgKq_unread{background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-interactive-bg-hover));min-width:18px;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;text-align:center;border-radius:9px;flex:none;padding:0 5px;font-size:11px;font-weight:600;line-height:17px}.s0QgKq_unreadMentioned{background:var(--dsw-alias-state-business-primary);min-width:18px;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;text-align:center;border-radius:9px;flex:none;padding:0 5px;font-size:11px;font-weight:600;line-height:17px}.s0QgKq_empty{color:var(--dsw-alias-label-tertiary);margin:0;padding:16px 12px;font-size:13px}.s0QgKq_emptyState{color:var(--dsw-alias-label-tertiary);text-align:center;flex-direction:column;align-items:center;gap:8px;margin-top:80px;padding:0 12px;font-size:13px;line-height:20px;display:flex}.s0QgKq_emptyState>svg{color:var(--dsw-alias-label-caption);margin-bottom:4px}.s0QgKq_fade{left:0;right:var(--dsh-session-list-edge-inset);background:linear-gradient(to bottom, transparent, var(--dsw-specific-sidebar-fill));pointer-events:none;height:24px;position:absolute;bottom:0}.s0QgKq_menuLayer{z-index:60;max-height:calc(100vh - 16px);position:fixed;overflow-y:auto}.s0QgKq_menuInline{z-index:30;position:absolute;top:32px;right:0}.s0QgKq_menu{border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1,var(--dsw-specific-sidebar-fill));min-width:200px;padding:4px;position:relative;box-shadow:0 6px 20px #0000002e}.s0QgKq_menuHeading{color:var(--dsw-alias-label-tertiary);padding:4px 8px 2px;font-size:11px;line-height:16px;display:block}.s0QgKq_menuItem{border-radius:var(--dsw-radius-sm);width:100%;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.s0QgKq_menuItem:hover{background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_check{color:var(--dsw-alias-state-business-primary);margin-left:auto}.s0QgKq_visuallyHidden{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.s0QgKq_rowWrap{position:relative}.s0QgKq_menuRename{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1,var(--dsw-specific-sidebar-fill));min-width:240px;padding:8px;box-shadow:0 6px 20px #0000002e}.s0QgKq_menuRename .s0QgKq_menuHeading{padding:0 0 6px}.s0QgKq_menuInput{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-sm);appearance:none;background:var(--dsw-alias-bg-base);width:100%;color:var(--dsw-alias-label-primary);font:inherit;outline:none;margin:2px 0 6px;padding:6px 8px;font-size:13px;line-height:20px}.s0QgKq_menuInput:focus-visible{border-color:var(--dsw-alias-state-business-primary)}.s0QgKq_menuInput::placeholder{color:var(--dsw-alias-label-tertiary)}.s0QgKq_menuActions{justify-content:flex-end;gap:6px;padding-top:2px;display:flex}.s0QgKq_menuConfirm{box-sizing:border-box;border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);font:inherit;cursor:pointer;border:1px solid #0000;padding:5px 12px;font-size:12px;line-height:18px}.s0QgKq_menuConfirm:hover:not(:disabled){filter:brightness(1.06)}.s0QgKq_menuConfirm:disabled{opacity:.5;cursor:default}.s0QgKq_menuCancel{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;padding:5px 12px;font-size:12px;line-height:18px}.s0QgKq_menuCancel:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_menuItem:disabled{opacity:.5;cursor:default}.s0QgKq_discoverSection{border-top:1px solid var(--dsw-alias-border-l3);margin-top:8px;padding-top:8px}.s0QgKq_discoverHeading{color:var(--dsw-alias-label-tertiary);margin:0 0 4px;padding:0 12px;font-size:11px;line-height:16px}.s0QgKq_discoverRow{border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-label-primary);align-items:center;gap:8px;padding:4px 12px;font-size:13px;line-height:18px;display:flex}.s0QgKq_discoverRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_discoverName{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}.s0QgKq_discoverMeta{color:var(--dsw-alias-label-tertiary);flex:none;font-size:11px}.s0QgKq_joinButton{border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-state-business-primary);font:inherit;cursor:pointer;background:0 0;flex:none;padding:2px 10px;font-size:12px}.s0QgKq_joinButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_joinButton:disabled{opacity:.5;cursor:default}.s0QgKq_leaveBody{flex-direction:column;gap:8px;min-width:0;display:flex}.s0QgKq_leaveCopy{color:var(--dsw-alias-label-primary);margin:0;font-size:14px;line-height:22px}.s0QgKq_leaveRoomName{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;margin:0;font-size:14px;line-height:22px}.s0QgKq_leaveRoomName strong{font-weight:600}.s0QgKq_leaveError{color:var(--dsw-alias-state-error-primary,#f85149);margin:0;font-size:12px;line-height:17px}.s0QgKq_footer{justify-content:flex-end;gap:8px;display:flex}.s0QgKq_leaveConfirmDanger{background:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-label-primary)}.s0QgKq_leaveConfirmDanger.s0QgKq_leaveConfirmDanger{color:var(--dsw-alias-label-primary)}.s0QgKq_leaveConfirmDanger:hover:not(:disabled){background:var(--dsw-alias-state-error-primary);filter:brightness(1.08)}.s0QgKq_leaveConfirmDanger:disabled{opacity:.5}";
1884
- const tagId$3 = "@sparkelf/dsh-group-chat/SidebarRooms.module.css";
1885
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
1911
+ const css$4 = ".s0QgKq_root{--dsh-session-list-edge-inset:var(--dsh-sidebar-inline-padding,12px);--dsh-session-list-scrollbar-width:5px;--dsh-session-list-scrollbar-offset:2px;box-sizing:border-box;flex-direction:column;flex:auto;width:100%;min-width:0;min-height:0;max-height:20vh;display:flex;position:relative}.s0QgKq_resizer{z-index:1;cursor:row-resize;touch-action:none;background:0 0;height:6px;position:absolute;top:-3px;left:0;right:0}.s0QgKq_resizer:after{content:\"\";background:var(--dsw-alias-border-l1,var(--dsw-alias-separator-primary));opacity:0;border-radius:1px;height:1px;transition:opacity .12s;position:absolute;top:3px;left:8px;right:8px}.s0QgKq_root:hover .s0QgKq_resizer:after,.s0QgKq_resizer:focus-visible:after{opacity:1}.s0QgKq_resizer:focus-visible{outline:none}.s0QgKq_resizer:focus-visible:after{background:var(--dsw-alias-brand-primary,var(--dsw-alias-label-primary));height:2px}.s0QgKq_sectionHeader{box-sizing:border-box;border-radius:var(--dsw-radius-md);height:36px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:flex-end;align-items:center;gap:4px;margin-bottom:4px;margin-right:-4px;padding-left:4px;display:flex;overflow:hidden}.s0QgKq_sectionLabel{white-space:nowrap;flex:none;min-width:0;max-width:45%;line-height:20px;overflow:hidden}.s0QgKq_searchSlot{box-sizing:border-box;flex:1;align-items:center;min-width:0;max-width:28px;margin-left:auto;padding-left:0;display:flex}.s0QgKq_searchSlotExpanded{box-sizing:border-box;flex:1;align-items:center;min-width:0;max-width:100%;margin-left:auto;padding-right:4px;display:flex}.s0QgKq_search,.s0QgKq_searchExpanded{box-sizing:border-box;border-radius:var(--dsw-radius-sm);width:100%;height:28px;color:var(--dsw-alias-label-secondary);cursor:text;background:0 0;border:none;flex:none;align-items:center;margin:0;padding:0;display:flex;overflow:hidden}.s0QgKq_searchExpanded{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);width:100%;height:30px;color:var(--dsw-alias-label-caption);margin-inline:0;padding:0 4px 0 0}.s0QgKq_iconButton{border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.s0QgKq_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_iconButton:focus-visible,.s0QgKq_searchButton:focus-visible,.s0QgKq_clearButton:focus-visible{outline:var(--dsw-focus-ring-width,2px) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:-2px}.s0QgKq_searchButton{border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:inherit;cursor:pointer;background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.s0QgKq_searchExpanded .s0QgKq_searchButton{width:28px;height:30px}.s0QgKq_searchButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_searchExpanded .s0QgKq_searchButton:hover{background:0 0}.s0QgKq_searchInput{width:0;min-width:0;color:var(--dsw-alias-label-primary);opacity:0;pointer-events:none;transition:opacity .12s var(--ds-ease-in-out);background:0 0;border:none;outline:none;flex:1;padding:0;font-size:13px;line-height:18px}.s0QgKq_searchExpanded .s0QgKq_searchInput{opacity:1;pointer-events:auto;margin-left:-2px}.s0QgKq_searchInput::placeholder{color:var(--dsw-alias-label-tertiary)}.s0QgKq_clearButton{border-radius:var(--dsw-radius-sm);width:24px;height:24px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.s0QgKq_clearButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_headerActions{flex:none;align-items:center;gap:4px;display:flex}.s0QgKq_viewWrap{display:flex;position:relative}.s0QgKq_listArea{min-height:0;margin-left:-4px;margin-right:calc(-1 * var(--dsh-session-list-edge-inset));flex-direction:column;flex:1;padding-left:4px;display:flex;position:relative}.s0QgKq_list{min-height:0;max-height:100%;margin-left:-4px;margin-right:var(--dsh-session-list-scrollbar-offset);padding-left:4px;padding-right:calc(var(--dsh-session-list-edge-inset) - var(--dsh-session-list-scrollbar-width) - var(--dsh-session-list-scrollbar-offset));scrollbar-gutter:stable;padding-bottom:8px;overflow-y:auto}.s0QgKq_flatList{margin:0;padding:0;list-style:none}.s0QgKq_flatList>*+*{margin-top:2px}.s0QgKq_sessionRow,.s0QgKq_sessionRowSelected{box-sizing:border-box;border-radius:var(--dsw-radius-sm);width:100%;height:32px;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:0 8px;font-size:14px;display:flex}.s0QgKq_sessionRow:hover,.s0QgKq_sessionRowSelected{background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_rowIcon{width:16px;color:var(--dsw-alias-label-secondary);flex:none;justify-content:center;align-items:center;display:flex}.s0QgKq_title{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.s0QgKq_time{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;font-size:12px;line-height:17px}.s0QgKq_unread{background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-interactive-bg-hover));min-width:18px;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;text-align:center;border-radius:9px;flex:none;padding:0 5px;font-size:11px;font-weight:600;line-height:17px}.s0QgKq_unreadMentioned{background:var(--dsw-alias-state-business-primary);min-width:18px;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;text-align:center;border-radius:9px;flex:none;padding:0 5px;font-size:11px;font-weight:600;line-height:17px}.s0QgKq_empty{color:var(--dsw-alias-label-tertiary);margin:0;padding:16px 12px;font-size:13px}.s0QgKq_emptyState{color:var(--dsw-alias-label-tertiary);text-align:center;flex-direction:column;align-items:center;gap:8px;margin-top:80px;padding:0 12px;font-size:13px;line-height:20px;display:flex}.s0QgKq_emptyState>svg{color:var(--dsw-alias-label-caption);margin-bottom:4px}.s0QgKq_fade{left:0;right:var(--dsh-session-list-edge-inset);background:linear-gradient(to bottom, transparent, var(--dsw-specific-sidebar-fill));pointer-events:none;height:24px;position:absolute;bottom:0}.s0QgKq_menuLayer{z-index:60;max-height:calc(100vh - 16px);position:fixed;overflow-y:auto}.s0QgKq_menuInline{z-index:30;position:absolute;top:32px;right:0}.s0QgKq_menu{border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1,var(--dsw-specific-sidebar-fill));min-width:200px;padding:4px;position:relative;box-shadow:0 6px 20px #0000002e}.s0QgKq_menuHeading{color:var(--dsw-alias-label-tertiary);padding:4px 8px 2px;font-size:11px;line-height:16px;display:block}.s0QgKq_menuItem{border-radius:var(--dsw-radius-sm);width:100%;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.s0QgKq_menuItem:hover{background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_check{color:var(--dsw-alias-state-business-primary);margin-left:auto}.s0QgKq_visuallyHidden{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.s0QgKq_rowWrap{position:relative}.s0QgKq_menuRename{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1,var(--dsw-specific-sidebar-fill));min-width:240px;padding:8px;box-shadow:0 6px 20px #0000002e}.s0QgKq_menuRename .s0QgKq_menuHeading{padding:0 0 6px}.s0QgKq_menuInput{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-sm);appearance:none;background:var(--dsw-alias-bg-base);width:100%;color:var(--dsw-alias-label-primary);font:inherit;outline:none;margin:2px 0 6px;padding:6px 8px;font-size:13px;line-height:20px}.s0QgKq_menuInput:focus-visible{border-color:var(--dsw-alias-state-business-primary)}.s0QgKq_menuInput::placeholder{color:var(--dsw-alias-label-tertiary)}.s0QgKq_menuActions{justify-content:flex-end;gap:6px;padding-top:2px;display:flex}.s0QgKq_menuConfirm{box-sizing:border-box;border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);font:inherit;cursor:pointer;border:1px solid #0000;padding:5px 12px;font-size:12px;line-height:18px}.s0QgKq_menuConfirm:hover:not(:disabled){filter:brightness(1.06)}.s0QgKq_menuConfirm:disabled{opacity:.5;cursor:default}.s0QgKq_menuCancel{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;padding:5px 12px;font-size:12px;line-height:18px}.s0QgKq_menuCancel:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_menuItem:disabled{opacity:.5;cursor:default}.s0QgKq_discoverSection{border-top:1px solid var(--dsw-alias-border-l3);margin-top:8px;padding-top:8px}.s0QgKq_discoverHeading{color:var(--dsw-alias-label-tertiary);margin:0 0 4px;padding:0 12px;font-size:11px;line-height:16px}.s0QgKq_discoverRow{border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-label-primary);align-items:center;gap:8px;padding:4px 12px;font-size:13px;line-height:18px;display:flex}.s0QgKq_discoverRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_discoverName{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}.s0QgKq_discoverMeta{color:var(--dsw-alias-label-tertiary);flex:none;font-size:11px}.s0QgKq_joinButton{border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-state-business-primary);font:inherit;cursor:pointer;background:0 0;flex:none;padding:2px 10px;font-size:12px}.s0QgKq_joinButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.s0QgKq_joinButton:disabled{opacity:.5;cursor:default}.s0QgKq_leaveBody{flex-direction:column;gap:8px;min-width:0;display:flex}.s0QgKq_leaveCopy{color:var(--dsw-alias-label-primary);margin:0;font-size:14px;line-height:22px}.s0QgKq_leaveRoomName{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;margin:0;font-size:14px;line-height:22px}.s0QgKq_leaveRoomName strong{font-weight:600}.s0QgKq_leaveError{color:var(--dsw-alias-state-error-primary,#f85149);margin:0;font-size:12px;line-height:17px}.s0QgKq_footer{justify-content:flex-end;gap:8px;display:flex}.s0QgKq_leaveConfirmDanger{background:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-label-primary)}.s0QgKq_leaveConfirmDanger.s0QgKq_leaveConfirmDanger{color:var(--dsw-alias-label-primary)}.s0QgKq_leaveConfirmDanger:hover:not(:disabled){background:var(--dsw-alias-state-error-primary);filter:brightness(1.08)}.s0QgKq_leaveConfirmDanger:disabled{opacity:.5}.s0QgKq_hitList{flex-direction:column;flex:none;gap:2px;max-height:45%;margin-bottom:4px;display:flex;overflow-y:auto}.s0QgKq_hitHint{color:var(--dsw-alias-label-tertiary);margin:2px 8px;font-size:12px;line-height:16px}.s0QgKq_hit{border-radius:var(--dsw-radius-sm);width:100%;color:inherit;text-align:left;cursor:pointer;background:0 0;border:none;flex-direction:column;gap:1px;padding:5px 8px;display:flex}.s0QgKq_hit:hover,.s0QgKq_hit:focus-visible{background:var(--dsw-alias-interactive-bg-hover);outline:none}.s0QgKq_hitHead{min-width:0;color:var(--dsw-alias-label-tertiary);align-items:baseline;gap:6px;font-size:11px;line-height:14px;display:flex}.s0QgKq_hitRoom{flex:none;font-weight:500}.s0QgKq_hitAuthor{text-overflow:ellipsis;white-space:nowrap;opacity:.8;min-width:0;overflow:hidden}.s0QgKq_hitText{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:12px;line-height:16px;display:block;overflow:hidden}.s0QgKq_mark{background:var(--dsw-alias-bg-brand-weak,#ffd66659);color:inherit;border-radius:2px;padding:0;font-weight:600}";
1912
+ const tagId$4 = "@sparkelf/dsh-group-chat/SidebarRooms.module.css";
1913
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
1886
1914
  const tag = document.createElement("style");
1887
1915
  tag.dataset.plugin = "@sparkelf/dsh-group-chat";
1888
- tag.dataset.pluginCss = tagId$3;
1889
- tag.textContent = css$3;
1916
+ tag.dataset.pluginCss = tagId$4;
1917
+ tag.textContent = css$4;
1890
1918
  document.head.appendChild(tag);
1891
1919
  }
1892
1920
  var SidebarRooms_module_css_default = {
1921
+ "hitRoom": "s0QgKq_hitRoom",
1922
+ "discoverSection": "s0QgKq_discoverSection",
1923
+ "sessionRowSelected": "s0QgKq_sessionRowSelected",
1924
+ "searchButton": "s0QgKq_searchButton",
1925
+ "searchExpanded": "s0QgKq_searchExpanded",
1926
+ "root": "s0QgKq_root",
1927
+ "menuInline": "s0QgKq_menuInline",
1893
1928
  "rowIcon": "s0QgKq_rowIcon",
1894
- "unread": "s0QgKq_unread",
1895
- "headerActions": "s0QgKq_headerActions",
1896
- "leaveRoomName": "s0QgKq_leaveRoomName",
1897
- "menu": "s0QgKq_menu",
1898
- "menuRename": "s0QgKq_menuRename",
1899
- "searchSlotExpanded": "s0QgKq_searchSlotExpanded",
1929
+ "time": "s0QgKq_time",
1930
+ "visuallyHidden": "s0QgKq_visuallyHidden",
1900
1931
  "rowWrap": "s0QgKq_rowWrap",
1901
- "menuConfirm": "s0QgKq_menuConfirm",
1902
- "viewWrap": "s0QgKq_viewWrap",
1932
+ "menu": "s0QgKq_menu",
1933
+ "search": "s0QgKq_search",
1934
+ "clearButton": "s0QgKq_clearButton",
1935
+ "leaveConfirmDanger": "s0QgKq_leaveConfirmDanger",
1936
+ "menuInput": "s0QgKq_menuInput",
1937
+ "discoverRow": "s0QgKq_discoverRow",
1938
+ "sectionHeader": "s0QgKq_sectionHeader",
1939
+ "menuActions": "s0QgKq_menuActions",
1903
1940
  "joinButton": "s0QgKq_joinButton",
1904
- "listArea": "s0QgKq_listArea",
1905
- "sessionRowSelected": "s0QgKq_sessionRowSelected",
1906
- "fade": "s0QgKq_fade",
1907
- "sectionLabel": "s0QgKq_sectionLabel",
1908
- "discoverHeading": "s0QgKq_discoverHeading",
1909
- "check": "s0QgKq_check",
1941
+ "menuHeading": "s0QgKq_menuHeading",
1910
1942
  "discoverName": "s0QgKq_discoverName",
1911
- "iconButton": "s0QgKq_iconButton",
1912
- "menuLayer": "s0QgKq_menuLayer",
1913
- "leaveCopy": "s0QgKq_leaveCopy",
1914
- "empty": "s0QgKq_empty",
1943
+ "discoverHeading": "s0QgKq_discoverHeading",
1944
+ "leaveRoomName": "s0QgKq_leaveRoomName",
1915
1945
  "emptyState": "s0QgKq_emptyState",
1916
- "clearButton": "s0QgKq_clearButton",
1917
- "discoverRow": "s0QgKq_discoverRow",
1918
- "leaveConfirmDanger": "s0QgKq_leaveConfirmDanger",
1919
- "unreadMentioned": "s0QgKq_unreadMentioned",
1920
- "searchButton": "s0QgKq_searchButton",
1921
- "search": "s0QgKq_search",
1922
- "searchInput": "s0QgKq_searchInput",
1923
- "discoverSection": "s0QgKq_discoverSection",
1946
+ "sectionLabel": "s0QgKq_sectionLabel",
1924
1947
  "sessionRow": "s0QgKq_sessionRow",
1925
- "menuItem": "s0QgKq_menuItem",
1926
- "menuCancel": "s0QgKq_menuCancel",
1927
1948
  "title": "s0QgKq_title",
1928
- "searchSlot": "s0QgKq_searchSlot",
1929
- "resizer": "s0QgKq_resizer",
1949
+ "fade": "s0QgKq_fade",
1950
+ "viewWrap": "s0QgKq_viewWrap",
1930
1951
  "flatList": "s0QgKq_flatList",
1931
- "root": "s0QgKq_root",
1932
- "time": "s0QgKq_time",
1933
- "menuInline": "s0QgKq_menuInline",
1934
- "menuHeading": "s0QgKq_menuHeading",
1935
- "sectionHeader": "s0QgKq_sectionHeader",
1936
- "menuInput": "s0QgKq_menuInput",
1952
+ "discoverMeta": "s0QgKq_discoverMeta",
1937
1953
  "list": "s0QgKq_list",
1938
- "searchExpanded": "s0QgKq_searchExpanded",
1939
- "visuallyHidden": "s0QgKq_visuallyHidden",
1940
- "leaveBody": "s0QgKq_leaveBody",
1954
+ "hitText": "s0QgKq_hitText",
1955
+ "menuConfirm": "s0QgKq_menuConfirm",
1956
+ "leaveCopy": "s0QgKq_leaveCopy",
1957
+ "check": "s0QgKq_check",
1958
+ "searchSlot": "s0QgKq_searchSlot",
1959
+ "hit": "s0QgKq_hit",
1960
+ "listArea": "s0QgKq_listArea",
1961
+ "menuRename": "s0QgKq_menuRename",
1962
+ "searchSlotExpanded": "s0QgKq_searchSlotExpanded",
1963
+ "menuCancel": "s0QgKq_menuCancel",
1964
+ "mark": "s0QgKq_mark",
1965
+ "empty": "s0QgKq_empty",
1966
+ "hitList": "s0QgKq_hitList",
1967
+ "menuLayer": "s0QgKq_menuLayer",
1968
+ "hitAuthor": "s0QgKq_hitAuthor",
1969
+ "hitHead": "s0QgKq_hitHead",
1970
+ "headerActions": "s0QgKq_headerActions",
1971
+ "unread": "s0QgKq_unread",
1941
1972
  "leaveError": "s0QgKq_leaveError",
1942
- "footer": "s0QgKq_footer",
1943
- "menuActions": "s0QgKq_menuActions",
1944
- "discoverMeta": "s0QgKq_discoverMeta"
1973
+ "unreadMentioned": "s0QgKq_unreadMentioned",
1974
+ "hitHint": "s0QgKq_hitHint",
1975
+ "iconButton": "s0QgKq_iconButton",
1976
+ "menuItem": "s0QgKq_menuItem",
1977
+ "leaveBody": "s0QgKq_leaveBody",
1978
+ "resizer": "s0QgKq_resizer",
1979
+ "searchInput": "s0QgKq_searchInput",
1980
+ "footer": "s0QgKq_footer"
1945
1981
  };
1946
1982
  //#endregion
1947
1983
  //#region src/client/SidebarRooms.tsx
@@ -1980,6 +2016,34 @@ window.__ModuleLoader__.load({
1980
2016
  * @param props - the injected copy resolver and the shared room store.
1981
2017
  * @returns the section header plus the flat room list.
1982
2018
  */
2019
+ /**
2020
+ * The hit text with the matched words marked.
2021
+ *
2022
+ * Splitting on the query gives the reader the one thing a result row has to offer: where in a
2023
+ * long message the words are. Case comes from the source text; only the comparison folds case.
2024
+ */
2025
+ const markQuery = (text, query) => {
2026
+ const needle = query.trim();
2027
+ if (needle.length === 0) return text;
2028
+ const parts = [];
2029
+ const lower = text.toLowerCase();
2030
+ const target = needle.toLowerCase();
2031
+ let from = 0;
2032
+ let at = lower.indexOf(target);
2033
+ let key = 0;
2034
+ while (at !== -1) {
2035
+ if (at > from) parts.push(text.slice(from, at));
2036
+ parts.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("mark", {
2037
+ className: SidebarRooms_module_css_default["mark"],
2038
+ children: text.slice(at, at + needle.length)
2039
+ }, key));
2040
+ key += 1;
2041
+ from = at + needle.length;
2042
+ at = lower.indexOf(target, from);
2043
+ }
2044
+ if (from < text.length) parts.push(text.slice(from));
2045
+ return parts;
2046
+ };
1983
2047
  function SidebarRooms(props) {
1984
2048
  const { t, tPreset, store } = props;
1985
2049
  const { rooms, activeRoomId, failure, searchQuery, discoverable } = (0, react.useSyncExternalStore)(store.subscribe, store.getState, store.getState);
@@ -1990,6 +2054,44 @@ window.__ModuleLoader__.load({
1990
2054
  const [joining, setJoining] = (0, react.useState)(void 0);
1991
2055
  const searchInput = (0, react.useRef)(null);
1992
2056
  /**
2057
+ * Opens the room a hit belongs to and scrolls to that message.
2058
+ *
2059
+ * The conversation is still loading when this fires, so the row is not in the DOM yet: poll
2060
+ * for the anchor instead of guessing one delay, and give up quietly rather than scrolling to
2061
+ * a stranger's message.
2062
+ */
2063
+ const openHit = (hit) => {
2064
+ store.open(hit.roomId);
2065
+ store.setSearch("");
2066
+ setSearchExpanded(false);
2067
+ if (typeof document === "undefined") return;
2068
+ let attempts = 0;
2069
+ const look = () => {
2070
+ const node = document.querySelector(`[data-group-chat-message="${hit.eventId}"]`);
2071
+ if (node !== null) {
2072
+ node.scrollIntoView({
2073
+ block: "center",
2074
+ behavior: "smooth"
2075
+ });
2076
+ return;
2077
+ }
2078
+ attempts += 1;
2079
+ if (attempts < 40) window.setTimeout(look, 250);
2080
+ };
2081
+ window.setTimeout(look, 400);
2082
+ };
2083
+ /**
2084
+ * Message hits for the same box the room rows are filtered by.
2085
+ *
2086
+ * One field, two questions: the rows below answer "which room is this" and this list answers
2087
+ * "where is this said". Two separate boxes made the reader choose which kind of search they
2088
+ * wanted before they knew what they were looking for.
2089
+ */
2090
+ const [hits, setHits] = (0, react.useState)([]);
2091
+ const [searching, setSearching] = (0, react.useState)(false);
2092
+ /** Issue counter so a slow query cannot overwrite the results of a later one. */
2093
+ const searchTicket = (0, react.useRef)(0);
2094
+ /**
1993
2095
  * Height of this region, in pixels, once the user has dragged it.
1994
2096
  *
1995
2097
  * `undefined` until either the saved value arrives or a drag happens: the region then keeps
@@ -2057,6 +2159,36 @@ window.__ModuleLoader__.load({
2057
2159
  document.addEventListener("pointerup", onUp);
2058
2160
  document.addEventListener("pointercancel", onUp);
2059
2161
  };
2162
+ /**
2163
+ * Message search, driven by the header box.
2164
+ *
2165
+ * Debounced and latest-wins: typing issues several queries, and an early one resolving late
2166
+ * would replace the results of a later, more specific one.
2167
+ */
2168
+ (0, react.useEffect)(() => {
2169
+ if (!searchExpanded) return;
2170
+ const trimmed = searchQuery.trim();
2171
+ if (trimmed.length === 0) {
2172
+ setHits([]);
2173
+ setSearching(false);
2174
+ return;
2175
+ }
2176
+ const ticket = searchTicket.current + 1;
2177
+ searchTicket.current = ticket;
2178
+ setSearching(true);
2179
+ const timer = setTimeout(() => {
2180
+ searchMessages(trimmed).then((found) => {
2181
+ if (searchTicket.current === ticket) setHits(found);
2182
+ }).catch(() => {
2183
+ if (searchTicket.current === ticket) setHits([]);
2184
+ }).finally(() => {
2185
+ if (searchTicket.current === ticket) setSearching(false);
2186
+ });
2187
+ }, 250);
2188
+ return () => {
2189
+ clearTimeout(timer);
2190
+ };
2191
+ }, [searchQuery, searchExpanded]);
2060
2192
  (0, react.useEffect)(() => {
2061
2193
  if (!searchExpanded) return;
2062
2194
  const onDown = (event) => {
@@ -2216,67 +2348,100 @@ window.__ModuleLoader__.load({
2216
2348
  }),
2217
2349
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2218
2350
  className: SidebarRooms_module_css_default.listArea,
2219
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2220
- className: SidebarRooms_module_css_default.list,
2221
- children: [
2222
- failure !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2223
- className: SidebarRooms_module_css_default.empty,
2224
- children: t(failure)
2225
- }),
2226
- failure === void 0 && rooms === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2227
- className: SidebarRooms_module_css_default.empty,
2228
- children: t("loading")
2229
- }),
2230
- failure === void 0 && rooms !== void 0 && visible.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2231
- className: SidebarRooms_module_css_default.emptyState,
2232
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQueueOutlineRegular, { size: 28 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: query.length > 0 ? t("searchEmpty") : t("emptyRooms") })]
2233
- }),
2234
- visible.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
2235
- className: SidebarRooms_module_css_default.flatList,
2236
- children: visible.map((room) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RoomRow, {
2237
- room,
2238
- t,
2239
- store,
2240
- selected: room.id === activeRoomId,
2241
- onOpen: () => store.open(room.id)
2242
- }) }, room.id))
2243
- }),
2244
- query.length > 0 && discoverable !== void 0 && joinable.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2245
- className: SidebarRooms_module_css_default.discoverSection,
2246
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2247
- className: SidebarRooms_module_css_default.discoverHeading,
2248
- children: t("discoverHeading")
2249
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
2351
+ children: [
2352
+ searchExpanded && query.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2353
+ className: SidebarRooms_module_css_default.hitList,
2354
+ role: "listbox",
2355
+ "aria-label": t("search"),
2356
+ children: searching && hits.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2357
+ className: SidebarRooms_module_css_default.hitHint,
2358
+ children: t("searching")
2359
+ }) : hits.length === 0 ? null : hits.map((hit) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
2360
+ type: "button",
2361
+ role: "option",
2362
+ "aria-selected": false,
2363
+ className: SidebarRooms_module_css_default.hit,
2364
+ onClick: () => {
2365
+ openHit(hit);
2366
+ },
2367
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2368
+ className: SidebarRooms_module_css_default.hitHead,
2369
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2370
+ className: SidebarRooms_module_css_default.hitRoom,
2371
+ children: hit.roomName
2372
+ }), hit.authorName === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2373
+ className: SidebarRooms_module_css_default.hitAuthor,
2374
+ children: hit.authorName
2375
+ })]
2376
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2377
+ className: SidebarRooms_module_css_default.hitText,
2378
+ children: markQuery(hit.text, searchQuery)
2379
+ })]
2380
+ }, `${hit.roomId}:${hit.eventId}`))
2381
+ }) : null,
2382
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2383
+ className: SidebarRooms_module_css_default.list,
2384
+ children: [
2385
+ failure !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2386
+ className: SidebarRooms_module_css_default.empty,
2387
+ children: t(failure)
2388
+ }),
2389
+ failure === void 0 && rooms === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2390
+ className: SidebarRooms_module_css_default.empty,
2391
+ children: t("loading")
2392
+ }),
2393
+ failure === void 0 && rooms !== void 0 && visible.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2394
+ className: SidebarRooms_module_css_default.emptyState,
2395
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQueueOutlineRegular, { size: 28 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: query.length > 0 ? t("searchEmpty") : t("emptyRooms") })]
2396
+ }),
2397
+ visible.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
2250
2398
  className: SidebarRooms_module_css_default.flatList,
2251
- children: joinable.map((room) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2252
- className: SidebarRooms_module_css_default.discoverRow,
2253
- children: [
2254
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2255
- className: SidebarRooms_module_css_default.discoverName,
2256
- children: room.name
2257
- }),
2258
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2259
- className: SidebarRooms_module_css_default.discoverMeta,
2260
- children: t("discoverMembers").replace("{count}", String(room.memberCount))
2261
- }),
2262
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2263
- type: "button",
2264
- className: SidebarRooms_module_css_default.joinButton,
2265
- disabled: joining === room.id,
2266
- onClick: () => {
2267
- onJoin(room.id);
2268
- },
2269
- children: joining === room.id ? t("joining") : t("joinRoom")
2270
- })
2271
- ]
2399
+ children: visible.map((room) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RoomRow, {
2400
+ room,
2401
+ t,
2402
+ store,
2403
+ selected: room.id === activeRoomId,
2404
+ onOpen: () => store.open(room.id)
2272
2405
  }) }, room.id))
2273
- })]
2274
- })
2275
- ]
2276
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2277
- className: SidebarRooms_module_css_default.fade,
2278
- "aria-hidden": "true"
2279
- })]
2406
+ }),
2407
+ query.length > 0 && discoverable !== void 0 && joinable.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2408
+ className: SidebarRooms_module_css_default.discoverSection,
2409
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2410
+ className: SidebarRooms_module_css_default.discoverHeading,
2411
+ children: t("discoverHeading")
2412
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
2413
+ className: SidebarRooms_module_css_default.flatList,
2414
+ children: joinable.map((room) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2415
+ className: SidebarRooms_module_css_default.discoverRow,
2416
+ children: [
2417
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2418
+ className: SidebarRooms_module_css_default.discoverName,
2419
+ children: room.name
2420
+ }),
2421
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2422
+ className: SidebarRooms_module_css_default.discoverMeta,
2423
+ children: t("discoverMembers").replace("{count}", String(room.memberCount))
2424
+ }),
2425
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2426
+ type: "button",
2427
+ className: SidebarRooms_module_css_default.joinButton,
2428
+ disabled: joining === room.id,
2429
+ onClick: () => {
2430
+ onJoin(room.id);
2431
+ },
2432
+ children: joining === room.id ? t("joining") : t("joinRoom")
2433
+ })
2434
+ ]
2435
+ }) }, room.id))
2436
+ })]
2437
+ })
2438
+ ]
2439
+ }),
2440
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2441
+ className: SidebarRooms_module_css_default.fade,
2442
+ "aria-hidden": "true"
2443
+ })
2444
+ ]
2280
2445
  }),
2281
2446
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreateRoomDialog, {
2282
2447
  t,
@@ -2771,21 +2936,123 @@ window.__ModuleLoader__.load({
2771
2936
  })]
2772
2937
  });
2773
2938
  }
2939
+ /**
2940
+ * Reads the quoted message out of a reply, if it has one.
2941
+ *
2942
+ * Returns `undefined` rather than a partial object: a quote with no preview has nothing to show,
2943
+ * and drawing an empty bar above the bubble would look like a rendering fault.
2944
+ *
2945
+ * @param message - the message data the node carries.
2946
+ * @returns the quote to draw, or `undefined` for an ordinary message.
2947
+ */
2948
+ /**
2949
+ * The text of a message, joined from its text blocks.
2950
+ *
2951
+ * Only `text` blocks contribute: an image or a file has no words to quote, and including a
2952
+ * placeholder for it would put text in the reply that the author never wrote.
2953
+ *
2954
+ * @param message - the message data the node carries.
2955
+ * @returns the collapsed text, or `''` when the message has none.
2956
+ */
2957
+ const previewOf = (message) => {
2958
+ const content = message?.content;
2959
+ if (typeof content === "string") return content.replace(/\s+/g, " ").trim();
2960
+ if (!Array.isArray(content)) return "";
2961
+ const parts = [];
2962
+ for (const block of content) {
2963
+ if (typeof block !== "object" || block === null) continue;
2964
+ const record = block;
2965
+ if (record["type"] !== "text") continue;
2966
+ const text = record["text"];
2967
+ if (typeof text === "string" && text.trim().length > 0) parts.push(text);
2968
+ }
2969
+ return parts.join(" ").replace(/\s+/g, " ").trim();
2970
+ };
2971
+ const quoteOf = (message) => {
2972
+ const content = message?.content;
2973
+ if (!Array.isArray(content)) return void 0;
2974
+ for (const block of content) {
2975
+ if (typeof block !== "object" || block === null) continue;
2976
+ const record = block;
2977
+ if (record["type"] !== "group-chat-quote") continue;
2978
+ const messageId = record["messageId"];
2979
+ const preview = record["preview"];
2980
+ if (typeof messageId !== "string" || messageId.length === 0) return void 0;
2981
+ if (typeof preview !== "string") return void 0;
2982
+ const authorName = typeof record["authorName"] === "string" && record["authorName"].trim().length > 0 ? record["authorName"].trim() : void 0;
2983
+ return {
2984
+ messageId,
2985
+ ...authorName === void 0 ? {} : { authorName },
2986
+ preview
2987
+ };
2988
+ }
2989
+ };
2990
+ /**
2991
+ * Creates the store.
2992
+ *
2993
+ * A plain observable rather than a framework store, for the same reason the room list is one:
2994
+ * every consumer is a component this plugin already owns, so the subscription contract is just
2995
+ * `useSyncExternalStore`.
2996
+ *
2997
+ * @returns the store the client entry hands to the components that need it.
2998
+ */
2999
+ const createQuoteStore = () => {
3000
+ const quotes = /* @__PURE__ */ new Map();
3001
+ const listeners = /* @__PURE__ */ new Set();
3002
+ const notify = () => {
3003
+ for (const listener of [...listeners]) listener();
3004
+ };
3005
+ return {
3006
+ getQuote: (roomId) => quotes.get(roomId),
3007
+ peek: (roomId) => quotes.get(roomId),
3008
+ subscribe: (listener) => {
3009
+ listeners.add(listener);
3010
+ return () => {
3011
+ listeners.delete(listener);
3012
+ };
3013
+ },
3014
+ start: (quote) => {
3015
+ quotes.set(quote.roomId, quote);
3016
+ notify();
3017
+ registerQuote(quote.roomId, quote).catch(() => void 0);
3018
+ },
3019
+ clear: (roomId) => {
3020
+ const had = quotes.delete(roomId);
3021
+ notify();
3022
+ if (had) clearQuote(roomId).catch(() => void 0);
3023
+ },
3024
+ clearLocal: (roomId) => {
3025
+ if (!quotes.delete(roomId)) return;
3026
+ notify();
3027
+ }
3028
+ };
3029
+ };
2774
3030
  //#endregion
2775
3031
  //#region \0dsh-css:/root/projects/dsh-plugins-plus/packages/group-chat/src/client/MessageSide.module.css.mjs
2776
- const css$2 = ".KXabfq_otherRow{display:contents}.KXabfq_otherRow.KXabfq_otherRow>*{align-items:flex-start}.KXabfq_otherRow{flex-direction:column;align-items:flex-start;min-width:0;max-width:100%;display:flex}.KXabfq_author{min-width:0;max-width:100%;color:var(--dsw-alias-label-tertiary);align-items:center;gap:6px;margin:0 0 4px 2px;font-size:12px;line-height:16px;display:flex}.KXabfq_authorName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.KXabfq_otherRow.KXabfq_otherRow>:not(.KXabfq_author){align-items:flex-start;max-width:100%}";
2777
- const tagId$2 = "@sparkelf/dsh-group-chat/MessageSide.module.css";
2778
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
3032
+ const css$3 = ".KXabfq_otherRow{display:contents}.KXabfq_otherRow.KXabfq_otherRow>*{align-items:flex-start}.KXabfq_otherRow{flex-direction:column;align-items:flex-start;min-width:0;max-width:100%;display:flex}.KXabfq_author{min-width:0;max-width:100%;color:var(--dsw-alias-label-tertiary);align-items:center;gap:6px;margin:0 0 4px 2px;font-size:12px;line-height:16px;display:flex}.KXabfq_authorName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.KXabfq_otherRow.KXabfq_otherRow>:not(.KXabfq_author){align-items:flex-start;max-width:100%}.KXabfq_quoteBar{box-sizing:border-box;background:var(--dsw-alias-bg-l2,#ffffff0a);border-radius:4px;align-items:stretch;gap:6px;max-width:min(420px,100%);margin-bottom:4px;padding:4px 8px 4px 0;display:flex;overflow:hidden}.KXabfq_quoteMark{background:var(--dsw-alias-brand-primary,currentcolor);opacity:.6;border-radius:1px;flex:none;width:2px}.KXabfq_quoteBody{min-width:0;color:var(--dsw-alias-label-secondary,inherit);align-items:baseline;gap:6px;font-size:12px;line-height:16px;display:flex}.KXabfq_quoteAuthor{white-space:nowrap;flex:none;font-weight:500}.KXabfq_quoteText{text-overflow:ellipsis;white-space:nowrap;opacity:.85;min-width:0;overflow:hidden}.KXabfq_selfRow{flex-direction:column;align-items:flex-end;min-width:0;max-width:100%;display:flex}.KXabfq_rowBody{align-items:flex-start;min-width:0;max-width:100%;display:flex;position:relative}.KXabfq_rowActions{opacity:0;align-items:center;transition:opacity .12s;display:flex;position:absolute;top:0;right:-28px}.KXabfq_otherRow:hover .KXabfq_rowActions,.KXabfq_rowActions:focus-within{opacity:1}.KXabfq_replyButton{width:calc(28px + var(--dsh-content-font-delta,0px));height:calc(28px + var(--dsh-content-font-delta,0px));border-radius:var(--dsw-radius-sm,6px);color:var(--dsw-alias-label-tertiary,inherit);cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;padding:6px;display:inline-flex}.KXabfq_replyButton:hover{background:var(--dsw-alias-bg-l2,#ffffff14);color:var(--dsw-alias-label-primary,inherit)}.KXabfq_replyButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,currentcolor);outline-offset:1px}.KXabfq_selfBody{justify-content:flex-end;align-items:flex-start;min-width:0;max-width:100%;display:flex;position:relative}.KXabfq_rowActionsSelf{opacity:0;align-items:center;transition:opacity .12s;display:flex;position:absolute;top:0;left:-28px}.KXabfq_selfRow:hover .KXabfq_rowActionsSelf,.KXabfq_rowActionsSelf:focus-within{opacity:1}";
3033
+ const tagId$3 = "@sparkelf/dsh-group-chat/MessageSide.module.css";
3034
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
2779
3035
  const tag = document.createElement("style");
2780
3036
  tag.dataset.plugin = "@sparkelf/dsh-group-chat";
2781
- tag.dataset.pluginCss = tagId$2;
2782
- tag.textContent = css$2;
3037
+ tag.dataset.pluginCss = tagId$3;
3038
+ tag.textContent = css$3;
2783
3039
  document.head.appendChild(tag);
2784
3040
  }
2785
3041
  var MessageSide_module_css_default = {
3042
+ "quoteBar": "KXabfq_quoteBar",
3043
+ "rowActions": "KXabfq_rowActions",
2786
3044
  "authorName": "KXabfq_authorName",
3045
+ "otherRow": "KXabfq_otherRow",
3046
+ "quoteBody": "KXabfq_quoteBody",
3047
+ "quoteAuthor": "KXabfq_quoteAuthor",
2787
3048
  "author": "KXabfq_author",
2788
- "otherRow": "KXabfq_otherRow"
3049
+ "replyButton": "KXabfq_replyButton",
3050
+ "quoteText": "KXabfq_quoteText",
3051
+ "rowActionsSelf": "KXabfq_rowActionsSelf",
3052
+ "selfRow": "KXabfq_selfRow",
3053
+ "quoteMark": "KXabfq_quoteMark",
3054
+ "rowBody": "KXabfq_rowBody",
3055
+ "selfBody": "KXabfq_selfBody"
2789
3056
  };
2790
3057
  //#endregion
2791
3058
  //#region src/client/MessageSide.tsx
@@ -2888,15 +3155,100 @@ window.__ModuleLoader__.load({
2888
3155
  * @param props - the official props plus this wrapper's placement inputs.
2889
3156
  * @returns the official view, wrapped only when the message is another author's room message.
2890
3157
  */
3158
+ /**
3159
+ * The bar above a bubble showing which message it answers.
3160
+ *
3161
+ * Drawn by this plugin rather than by the official view: the quote travels as a content block
3162
+ * whose type the official renderer does not know, so it would otherwise be dropped. The bar sits
3163
+ * outside the bubble so the reply's own text keeps the official layout.
3164
+ *
3165
+ * @param props - the quote to show.
3166
+ * @returns the bar, or `null` when there is nothing worth quoting.
3167
+ */
3168
+ const QuoteBar = ({ quote }) => {
3169
+ if (quote.preview.length === 0) return null;
3170
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3171
+ className: MessageSide_module_css_default["quoteBar"],
3172
+ "data-group-chat-quote": quote.messageId,
3173
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3174
+ className: MessageSide_module_css_default["quoteMark"],
3175
+ "aria-hidden": "true"
3176
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3177
+ className: MessageSide_module_css_default["quoteBody"],
3178
+ children: [quote.authorName === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3179
+ className: MessageSide_module_css_default["quoteAuthor"],
3180
+ children: quote.authorName
3181
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3182
+ className: MessageSide_module_css_default["quoteText"],
3183
+ children: quote.preview
3184
+ })]
3185
+ })]
3186
+ });
3187
+ };
3188
+ /**
3189
+ * The control that starts a reply to one message.
3190
+ *
3191
+ * Rendered inside the wrapper this plugin already draws around another author's row, which is
3192
+ * the only place the message id is known. It reads its own hover state so the button appears
3193
+ * over the row it belongs to and nowhere else.
3194
+ *
3195
+ * @param props - the message it replies to, and the store the pick lands in.
3196
+ * @returns the button, or `null` when the message cannot be replied to.
3197
+ */
3198
+ const ReplyControl = (props) => {
3199
+ const { roomId, messageId, authorName, preview, quotes, t } = props;
3200
+ if (preview.length === 0) return null;
3201
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3202
+ type: "button",
3203
+ className: MessageSide_module_css_default["replyButton"],
3204
+ "data-group-chat-reply": "",
3205
+ "aria-label": t("reply"),
3206
+ title: t("reply"),
3207
+ onClick: () => {
3208
+ quotes.start({
3209
+ roomId,
3210
+ messageId,
3211
+ preview,
3212
+ ...authorName === void 0 ? {} : { authorName }
3213
+ });
3214
+ },
3215
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
3216
+ width: "13",
3217
+ height: "13",
3218
+ viewBox: "0 0 16 16",
3219
+ fill: "none",
3220
+ stroke: "currentColor",
3221
+ strokeWidth: "1.5",
3222
+ strokeLinecap: "round",
3223
+ strokeLinejoin: "round",
3224
+ "aria-hidden": "true",
3225
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M6 4 2.5 7.5 6 11" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2.5 7.5h7A3.5 3.5 0 0 1 13 11v1.5" })]
3226
+ })
3227
+ });
3228
+ };
2891
3229
  const MessageSide = (props) => {
2892
- const { node, Official, getSelfId, subscribeSelf, sided, getRoster } = props;
3230
+ const { node, Official, getSelfId, subscribeSelf, sided, getRoster, quotes } = props;
2893
3231
  const selfId = (0, react.useSyncExternalStore)(subscribeSelf, getSelfId, getSelfId);
2894
3232
  if (typeof Official !== "function" && typeof Official !== "object") return null;
2895
3233
  const view = (0, react.createElement)(Official, props);
2896
3234
  const message = node?.data;
2897
- if ((sided ? messageSide(message, selfId) : void 0) !== "other") return view;
3235
+ const side = sided ? messageSide(message, selfId) : void 0;
3236
+ const quote = quoteOf(message);
2898
3237
  const roomId = message?.source?.roomId;
2899
- const member = authorOf(message, typeof roomId === "string" && roomId.length > 0 ? getRoster(roomId) : void 0);
3238
+ const roomKnown = typeof roomId === "string" && roomId.length > 0;
3239
+ const sourceMessageId = message?.source?.messageId;
3240
+ const rawId = message?.id;
3241
+ const messageId = typeof sourceMessageId === "string" && sourceMessageId.length > 0 ? sourceMessageId : typeof rawId === "string" && rawId.length > 0 ? rawId : void 0;
3242
+ if (side === void 0 || !roomKnown) {
3243
+ if (quote === void 0) return view;
3244
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3245
+ className: MessageSide_module_css_default["selfRow"],
3246
+ "data-group-chat-side": "self",
3247
+ ...messageId === void 0 ? {} : { "data-group-chat-message": messageId },
3248
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuoteBar, { quote }), view]
3249
+ });
3250
+ }
3251
+ const member = authorOf(message, getRoster(roomId));
2900
3252
  const name = authorNameOf(member);
2901
3253
  const head = name === void 0 || member === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2902
3254
  className: MessageSide_module_css_default["author"],
@@ -2910,10 +3262,40 @@ window.__ModuleLoader__.load({
2910
3262
  children: name
2911
3263
  })]
2912
3264
  });
3265
+ const rawPreview = previewOf(message);
3266
+ const preview = name === void 0 ? rawPreview : rawPreview.replace(new RegExp(`^${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*[::]\\s*`), "");
3267
+ const actions = quotes !== void 0 && messageId !== void 0 && preview.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3268
+ className: side === "self" ? MessageSide_module_css_default["rowActionsSelf"] : MessageSide_module_css_default["rowActions"],
3269
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplyControl, {
3270
+ roomId,
3271
+ messageId,
3272
+ ...name === void 0 ? {} : { authorName: name },
3273
+ preview,
3274
+ quotes,
3275
+ t: props.tOwn ?? ((key) => key)
3276
+ })
3277
+ }) : null;
3278
+ if (side === "self") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3279
+ className: MessageSide_module_css_default["selfRow"],
3280
+ "data-group-chat-side": "self",
3281
+ ...messageId === void 0 ? {} : { "data-group-chat-message": messageId },
3282
+ children: [quote === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuoteBar, { quote }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3283
+ className: MessageSide_module_css_default["selfBody"],
3284
+ children: [view, actions]
3285
+ })]
3286
+ });
2913
3287
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2914
3288
  className: MessageSide_module_css_default["otherRow"],
2915
3289
  "data-group-chat-side": "other",
2916
- children: [head, view]
3290
+ ...messageId === void 0 ? {} : { "data-group-chat-message": messageId },
3291
+ children: [
3292
+ head,
3293
+ quote === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuoteBar, { quote }),
3294
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3295
+ className: MessageSide_module_css_default["rowBody"],
3296
+ children: [view, actions]
3297
+ })
3298
+ ]
2917
3299
  });
2918
3300
  };
2919
3301
  //#endregion
@@ -2948,56 +3330,56 @@ window.__ModuleLoader__.load({
2948
3330
  };
2949
3331
  //#endregion
2950
3332
  //#region \0dsh-css:/root/projects/dsh-plugins-plus/packages/group-chat/src/client/MembersPanel.module.css.mjs
2951
- const css$1 = ".VeQVAa_root{box-sizing:border-box;flex-direction:column;gap:16px;min-width:200px;padding:12px 12px 20px;display:flex}.VeQVAa_section{flex-direction:column;gap:8px;min-width:0;display:flex}.VeQVAa_section+.VeQVAa_section{border-top:1px solid var(--dsw-alias-border-l3);padding-top:14px}.VeQVAa_sectionHeader{align-items:center;gap:6px;min-width:0;display:flex}.VeQVAa_sectionToggle{min-width:0;color:inherit;font:inherit;cursor:pointer;text-align:start;background:0 0;border:0;align-items:center;gap:4px;padding:0;display:flex}.VeQVAa_caret{width:10px;color:var(--dsw-alias-label-tertiary);flex:none;font-size:10px;line-height:12px}.VeQVAa_sectionBody{flex-direction:column;gap:8px;min-width:0;display:flex}.VeQVAa_sectionLabel{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:18px}.VeQVAa_count{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:16px}.VeQVAa_searchToggle{border-radius:var(--dsw-radius-sm);width:20px;height:20px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;flex:none;justify-content:center;align-items:center;margin-left:auto;padding:0;display:flex}.VeQVAa_searchToggle:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.VeQVAa_searchToggle:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.VeQVAa_linkButton{border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-state-business-primary);font:inherit;cursor:pointer;background:0 0;border:none;margin-left:auto;padding:2px 6px;font-size:12px}.VeQVAa_linkButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.VeQVAa_announcementText{border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);white-space:pre-wrap;overflow-wrap:anywhere;margin:0;padding:8px 10px;font-size:13px;line-height:20px}.VeQVAa_editor{flex-direction:column;gap:8px;display:flex}.VeQVAa_textarea{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm);width:100%;color:var(--dsw-alias-label-primary);font:inherit;resize:vertical;background:0 0;padding:8px 10px;font-size:13px;line-height:20px}.VeQVAa_textarea:focus{border-color:var(--dsw-alias-state-business-primary);outline:none}.VeQVAa_editorFooter{align-items:center;gap:6px;display:flex}.VeQVAa_editorFooter .VeQVAa_hint{margin-right:auto}.VeQVAa_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:16px}.VeQVAa_unavailable{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.VeQVAa_error{color:var(--dsw-alias-state-error-primary,var(--dsw-alias-label-primary));margin:0;font-size:12px;line-height:16px}.VeQVAa_notice{color:var(--dsw-alias-label-tertiary);margin:0;padding:16px 12px;font-size:12px;line-height:18px}.VeQVAa_search{min-width:0}.VeQVAa_list{flex-direction:column;margin:0;padding:0;list-style:none;display:flex}.VeQVAa_row{border-radius:var(--dsw-radius-sm);align-items:center;gap:8px;min-width:0;padding:5px 4px;display:flex}.VeQVAa_row:hover{background:var(--dsw-alias-interactive-bg-hover)}.VeQVAa_name{min-width:0;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;flex:auto;font-size:13px;line-height:18px;overflow:hidden}.VeQVAa_fileButton{width:100%;color:inherit;font:inherit;text-align:start;cursor:pointer;border-radius:var(--dsw-alias-border-radius-s);background:0 0;border:0;align-items:center;gap:8px;padding:0;display:flex}.VeQVAa_fileButton:hover .VeQVAa_name{text-decoration:underline}.VeQVAa_filePicker{display:none}.VeQVAa_crumbs{flex-wrap:wrap;align-items:center;gap:2px;min-width:0;display:flex}.VeQVAa_crumbGroup{align-items:center;gap:2px;min-width:0;display:inline-flex}.VeQVAa_crumb{text-overflow:ellipsis;white-space:nowrap;max-width:120px;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:0;padding:0 2px;font-size:11px;overflow:hidden}.VeQVAa_crumb:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.VeQVAa_crumbSep{color:var(--dsw-alias-label-tertiary);font-size:11px}.VeQVAa_refresh{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;margin-inline-start:auto;padding:0 4px;font-size:12px;line-height:16px}.VeQVAa_refresh:hover{color:var(--dsw-alias-label-primary)}.VeQVAa_preview{border:1px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-alias-border-radius-m);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-bg-base));margin-top:8px;overflow:hidden}.VeQVAa_previewHeader{border-bottom:1px solid var(--dsw-alias-border-l1);align-items:center;gap:8px;padding:6px 8px;display:flex}.VeQVAa_previewTitle{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;font-size:12px;font-weight:500;overflow:hidden}.VeQVAa_previewClose{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;flex:none;padding:0 4px;font-size:14px;line-height:16px}.VeQVAa_previewClose:hover{color:var(--dsw-alias-label-primary)}.VeQVAa_previewImage{border-radius:var(--dsw-alias-border-radius-s);background:var(--dsw-alias-bg-base);max-width:100%;height:auto;display:block}.VeQVAa_previewBody{max-height:240px;font-family:var(--dsw-alias-font-family-mono,monospace);white-space:pre-wrap;word-break:break-word;margin:0;padding:8px;font-size:11px;line-height:16px;overflow:auto}.VeQVAa_fileIcon{text-align:center;flex:none;width:16px;font-size:12px;line-height:16px}.VeQVAa_fileSize{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;font-size:11px}.VeQVAa_remove{border-radius:var(--dsw-radius-sm);width:20px;height:20px;color:var(--dsw-alias-label-tertiary);opacity:0;cursor:pointer;background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;transition:opacity .12s,background .12s,color .12s;display:inline-flex}.VeQVAa_row:hover .VeQVAa_remove,.VeQVAa_remove:focus-visible{opacity:1}.VeQVAa_remove:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-state-error-primary)}.VeQVAa_selfTag{border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-tertiary);flex:none;padding:0 5px;font-size:11px;line-height:16px}.VeQVAa_ownerTag{border:1px solid color-mix(in srgb, var(--dsw-alias-state-warning-primary,#f7ad31) 40%, transparent);border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-state-warning-primary,#f7ad31);flex:none;padding:0 5px;font-size:11px;line-height:16px}";
2952
- const tagId$1 = "@sparkelf/dsh-group-chat/MembersPanel.module.css";
2953
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
3333
+ const css$2 = ".VeQVAa_root{box-sizing:border-box;flex-direction:column;gap:16px;min-width:200px;padding:12px 12px 20px;display:flex}.VeQVAa_section{flex-direction:column;gap:8px;min-width:0;display:flex}.VeQVAa_section+.VeQVAa_section{border-top:1px solid var(--dsw-alias-border-l3);padding-top:14px}.VeQVAa_sectionHeader{align-items:center;gap:6px;min-width:0;display:flex}.VeQVAa_sectionToggle{min-width:0;color:inherit;font:inherit;cursor:pointer;text-align:start;background:0 0;border:0;align-items:center;gap:4px;padding:0;display:flex}.VeQVAa_caret{width:10px;color:var(--dsw-alias-label-tertiary);flex:none;font-size:10px;line-height:12px}.VeQVAa_sectionBody{flex-direction:column;gap:8px;min-width:0;display:flex}.VeQVAa_sectionLabel{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:18px}.VeQVAa_count{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:16px}.VeQVAa_searchToggle{border-radius:var(--dsw-radius-sm);width:20px;height:20px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;flex:none;justify-content:center;align-items:center;margin-left:auto;padding:0;display:flex}.VeQVAa_searchToggle:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.VeQVAa_searchToggle:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:1px}.VeQVAa_linkButton{border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-state-business-primary);font:inherit;cursor:pointer;background:0 0;border:none;margin-left:auto;padding:2px 6px;font-size:12px}.VeQVAa_linkButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.VeQVAa_announcementText{border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);white-space:pre-wrap;overflow-wrap:anywhere;margin:0;padding:8px 10px;font-size:13px;line-height:20px}.VeQVAa_editor{flex-direction:column;gap:8px;display:flex}.VeQVAa_textarea{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm);width:100%;color:var(--dsw-alias-label-primary);font:inherit;resize:vertical;background:0 0;padding:8px 10px;font-size:13px;line-height:20px}.VeQVAa_textarea:focus{border-color:var(--dsw-alias-state-business-primary);outline:none}.VeQVAa_editorFooter{align-items:center;gap:6px;display:flex}.VeQVAa_editorFooter .VeQVAa_hint{margin-right:auto}.VeQVAa_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:16px}.VeQVAa_unavailable{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.VeQVAa_error{color:var(--dsw-alias-state-error-primary,var(--dsw-alias-label-primary));margin:0;font-size:12px;line-height:16px}.VeQVAa_notice{color:var(--dsw-alias-label-tertiary);margin:0;padding:16px 12px;font-size:12px;line-height:18px}.VeQVAa_search{min-width:0}.VeQVAa_list{flex-direction:column;margin:0;padding:0;list-style:none;display:flex}.VeQVAa_row{border-radius:var(--dsw-radius-sm);align-items:center;gap:8px;min-width:0;padding:5px 4px;display:flex}.VeQVAa_row:hover{background:var(--dsw-alias-interactive-bg-hover)}.VeQVAa_name{min-width:0;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;flex:auto;font-size:13px;line-height:18px;overflow:hidden}.VeQVAa_fileButton{width:100%;color:inherit;font:inherit;text-align:start;cursor:pointer;border-radius:var(--dsw-alias-border-radius-s);background:0 0;border:0;align-items:center;gap:8px;padding:0;display:flex}.VeQVAa_fileButton:hover .VeQVAa_name{text-decoration:underline}.VeQVAa_filePicker{display:none}.VeQVAa_crumbs{flex-wrap:wrap;align-items:center;gap:2px;min-width:0;display:flex}.VeQVAa_crumbGroup{align-items:center;gap:2px;min-width:0;display:inline-flex}.VeQVAa_crumb{text-overflow:ellipsis;white-space:nowrap;max-width:120px;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:0;padding:0 2px;font-size:11px;overflow:hidden}.VeQVAa_crumb:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.VeQVAa_crumbSep{color:var(--dsw-alias-label-tertiary);font-size:11px}.VeQVAa_refresh{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;margin-inline-start:auto;padding:0 4px;font-size:12px;line-height:16px}.VeQVAa_refresh:hover{color:var(--dsw-alias-label-primary)}.VeQVAa_preview{border:1px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-alias-border-radius-m);background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-bg-base));margin-top:8px;overflow:hidden}.VeQVAa_previewHeader{border-bottom:1px solid var(--dsw-alias-border-l1);align-items:center;gap:8px;padding:6px 8px;display:flex}.VeQVAa_previewTitle{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;font-size:12px;font-weight:500;overflow:hidden}.VeQVAa_previewClose{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;flex:none;padding:0 4px;font-size:14px;line-height:16px}.VeQVAa_previewClose:hover{color:var(--dsw-alias-label-primary)}.VeQVAa_previewImage{border-radius:var(--dsw-alias-border-radius-s);background:var(--dsw-alias-bg-base);max-width:100%;height:auto;display:block}.VeQVAa_previewBody{max-height:240px;font-family:var(--dsw-alias-font-family-mono,monospace);white-space:pre-wrap;word-break:break-word;margin:0;padding:8px;font-size:11px;line-height:16px;overflow:auto}.VeQVAa_fileIcon{text-align:center;flex:none;width:16px;font-size:12px;line-height:16px}.VeQVAa_fileSize{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;font-size:11px}.VeQVAa_remove{border-radius:var(--dsw-radius-sm);width:20px;height:20px;color:var(--dsw-alias-label-tertiary);opacity:0;cursor:pointer;background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;transition:opacity .12s,background .12s,color .12s;display:inline-flex}.VeQVAa_row:hover .VeQVAa_remove,.VeQVAa_remove:focus-visible{opacity:1}.VeQVAa_remove:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-state-error-primary)}.VeQVAa_selfTag{border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-tertiary);flex:none;padding:0 5px;font-size:11px;line-height:16px}.VeQVAa_ownerTag{border:1px solid color-mix(in srgb, var(--dsw-alias-state-warning-primary,#f7ad31) 40%, transparent);border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-state-warning-primary,#f7ad31);flex:none;padding:0 5px;font-size:11px;line-height:16px}";
3334
+ const tagId$2 = "@sparkelf/dsh-group-chat/MembersPanel.module.css";
3335
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
2954
3336
  const tag = document.createElement("style");
2955
3337
  tag.dataset.plugin = "@sparkelf/dsh-group-chat";
2956
- tag.dataset.pluginCss = tagId$1;
2957
- tag.textContent = css$1;
3338
+ tag.dataset.pluginCss = tagId$2;
3339
+ tag.textContent = css$2;
2958
3340
  document.head.appendChild(tag);
2959
3341
  }
2960
3342
  var MembersPanel_module_css_default = {
2961
- "announcementText": "VeQVAa_announcementText",
2962
- "notice": "VeQVAa_notice",
2963
- "name": "VeQVAa_name",
2964
- "previewClose": "VeQVAa_previewClose",
2965
- "unavailable": "VeQVAa_unavailable",
2966
- "crumbGroup": "VeQVAa_crumbGroup",
2967
- "textarea": "VeQVAa_textarea",
2968
- "search": "VeQVAa_search",
2969
- "linkButton": "VeQVAa_linkButton",
2970
- "fileButton": "VeQVAa_fileButton",
3343
+ "count": "VeQVAa_count",
2971
3344
  "previewImage": "VeQVAa_previewImage",
2972
- "section": "VeQVAa_section",
3345
+ "hint": "VeQVAa_hint",
2973
3346
  "sectionToggle": "VeQVAa_sectionToggle",
2974
- "fileSize": "VeQVAa_fileSize",
2975
- "crumbSep": "VeQVAa_crumbSep",
2976
- "selfTag": "VeQVAa_selfTag",
2977
3347
  "ownerTag": "VeQVAa_ownerTag",
2978
- "sectionBody": "VeQVAa_sectionBody",
2979
3348
  "preview": "VeQVAa_preview",
2980
- "previewTitle": "VeQVAa_previewTitle",
2981
- "sectionHeader": "VeQVAa_sectionHeader",
2982
- "remove": "VeQVAa_remove",
2983
- "editor": "VeQVAa_editor",
2984
- "error": "VeQVAa_error",
2985
- "caret": "VeQVAa_caret",
2986
- "count": "VeQVAa_count",
3349
+ "unavailable": "VeQVAa_unavailable",
3350
+ "previewClose": "VeQVAa_previewClose",
3351
+ "fileIcon": "VeQVAa_fileIcon",
2987
3352
  "crumb": "VeQVAa_crumb",
2988
- "row": "VeQVAa_row",
3353
+ "crumbGroup": "VeQVAa_crumbGroup",
3354
+ "fileButton": "VeQVAa_fileButton",
2989
3355
  "filePicker": "VeQVAa_filePicker",
3356
+ "root": "VeQVAa_root",
3357
+ "sectionHeader": "VeQVAa_sectionHeader",
3358
+ "error": "VeQVAa_error",
2990
3359
  "refresh": "VeQVAa_refresh",
2991
3360
  "previewHeader": "VeQVAa_previewHeader",
3361
+ "sectionBody": "VeQVAa_sectionBody",
3362
+ "row": "VeQVAa_row",
3363
+ "fileSize": "VeQVAa_fileSize",
3364
+ "previewTitle": "VeQVAa_previewTitle",
3365
+ "remove": "VeQVAa_remove",
3366
+ "list": "VeQVAa_list",
3367
+ "crumbs": "VeQVAa_crumbs",
3368
+ "caret": "VeQVAa_caret",
3369
+ "linkButton": "VeQVAa_linkButton",
3370
+ "crumbSep": "VeQVAa_crumbSep",
3371
+ "name": "VeQVAa_name",
3372
+ "selfTag": "VeQVAa_selfTag",
3373
+ "search": "VeQVAa_search",
3374
+ "notice": "VeQVAa_notice",
3375
+ "searchToggle": "VeQVAa_searchToggle",
2992
3376
  "editorFooter": "VeQVAa_editorFooter",
2993
- "root": "VeQVAa_root",
3377
+ "announcementText": "VeQVAa_announcementText",
3378
+ "editor": "VeQVAa_editor",
2994
3379
  "previewBody": "VeQVAa_previewBody",
2995
- "fileIcon": "VeQVAa_fileIcon",
3380
+ "section": "VeQVAa_section",
2996
3381
  "sectionLabel": "VeQVAa_sectionLabel",
2997
- "hint": "VeQVAa_hint",
2998
- "searchToggle": "VeQVAa_searchToggle",
2999
- "list": "VeQVAa_list",
3000
- "crumbs": "VeQVAa_crumbs"
3382
+ "textarea": "VeQVAa_textarea"
3001
3383
  };
3002
3384
  //#endregion
3003
3385
  //#region src/client/MembersPanel.tsx
@@ -3610,18 +3992,18 @@ window.__ModuleLoader__.load({
3610
3992
  }
3611
3993
  //#endregion
3612
3994
  //#region \0dsh-css:/root/projects/dsh-plugins-plus/packages/group-chat/src/client/GuideEntry.module.css.mjs
3613
- const css = "._0Vnsuq_entry{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-xl);background:var(--dsw-alias-bg-layer-1);width:380px;max-width:100%;min-height:56px;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;align-items:center;gap:14px;padding:14px 20px;display:flex}._0Vnsuq_entry:hover{background:var(--dsw-alias-interactive-bg-hover)}._0Vnsuq_icon{width:26px;height:26px;color:var(--dsw-alias-label-secondary);flex:none;justify-content:center;align-items:center;display:flex}._0Vnsuq_text{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}._0Vnsuq_title{text-overflow:ellipsis;white-space:nowrap;font-size:14px;line-height:1.4;overflow:hidden}._0Vnsuq_description{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:1.4;overflow:hidden}";
3614
- const tagId = "@sparkelf/dsh-group-chat/GuideEntry.module.css";
3615
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
3995
+ const css$1 = "._0Vnsuq_entry{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-xl);background:var(--dsw-alias-bg-layer-1);width:380px;max-width:100%;min-height:56px;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;align-items:center;gap:14px;padding:14px 20px;display:flex}._0Vnsuq_entry:hover{background:var(--dsw-alias-interactive-bg-hover)}._0Vnsuq_icon{width:26px;height:26px;color:var(--dsw-alias-label-secondary);flex:none;justify-content:center;align-items:center;display:flex}._0Vnsuq_text{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}._0Vnsuq_title{text-overflow:ellipsis;white-space:nowrap;font-size:14px;line-height:1.4;overflow:hidden}._0Vnsuq_description{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:1.4;overflow:hidden}";
3996
+ const tagId$1 = "@sparkelf/dsh-group-chat/GuideEntry.module.css";
3997
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
3616
3998
  const tag = document.createElement("style");
3617
3999
  tag.dataset.plugin = "@sparkelf/dsh-group-chat";
3618
- tag.dataset.pluginCss = tagId;
3619
- tag.textContent = css;
4000
+ tag.dataset.pluginCss = tagId$1;
4001
+ tag.textContent = css$1;
3620
4002
  document.head.appendChild(tag);
3621
4003
  }
3622
4004
  var GuideEntry_module_css_default = {
3623
- "title": "_0Vnsuq_title",
3624
4005
  "text": "_0Vnsuq_text",
4006
+ "title": "_0Vnsuq_title",
3625
4007
  "icon": "_0Vnsuq_icon",
3626
4008
  "description": "_0Vnsuq_description",
3627
4009
  "entry": "_0Vnsuq_entry"
@@ -3680,6 +4062,211 @@ window.__ModuleLoader__.load({
3680
4062
  });
3681
4063
  }
3682
4064
  //#endregion
4065
+ //#region \0dsh-css:/root/projects/dsh-plugins-plus/packages/group-chat/src/client/QuoteComposer.module.css.mjs
4066
+ const css = ".AK6KxW_button{width:24px;height:24px;color:var(--dsw-alias-label-secondary,inherit);cursor:pointer;opacity:.7;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:0;transition:opacity .12s,background-color .12s;display:inline-flex}.AK6KxW_button:hover{opacity:1;background:var(--dsw-alias-bg-l2,#ffffff14)}.AK6KxW_button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,currentcolor);outline-offset:1px}.AK6KxW_bar{box-sizing:border-box;width:100%;max-width:var(--dsh-chat-content-width,100%);background:var(--dsw-alias-bg-l2,#ffffff0a);border-radius:8px;align-items:center;gap:6px;margin:0 auto 4px;padding:6px 8px;display:flex}.AK6KxW_mark{background:var(--dsw-alias-brand-primary,currentcolor);opacity:.6;border-radius:1px;flex:none;align-self:stretch;width:2px}.AK6KxW_body{min-width:0;color:var(--dsw-alias-label-secondary,inherit);align-items:baseline;gap:6px;font-size:12px;line-height:16px;display:flex}.AK6KxW_author{white-space:nowrap;flex:none;font-weight:500}.AK6KxW_text{text-overflow:ellipsis;white-space:nowrap;opacity:.85;min-width:0;overflow:hidden}.AK6KxW_dismiss{width:20px;height:20px;color:var(--dsw-alias-label-secondary,inherit);cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;margin-left:auto;padding:0;font-size:16px;line-height:1}.AK6KxW_dismiss:hover{background:var(--dsw-alias-bg-l3,#ffffff1a);color:var(--dsw-alias-label-primary,inherit)}";
4067
+ const tagId = "@sparkelf/dsh-group-chat/QuoteComposer.module.css";
4068
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
4069
+ const tag = document.createElement("style");
4070
+ tag.dataset.plugin = "@sparkelf/dsh-group-chat";
4071
+ tag.dataset.pluginCss = tagId;
4072
+ tag.textContent = css;
4073
+ document.head.appendChild(tag);
4074
+ }
4075
+ var QuoteComposer_module_css_default = {
4076
+ "bar": "AK6KxW_bar",
4077
+ "mark": "AK6KxW_mark",
4078
+ "body": "AK6KxW_body",
4079
+ "text": "AK6KxW_text",
4080
+ "dismiss": "AK6KxW_dismiss",
4081
+ "button": "AK6KxW_button",
4082
+ "author": "AK6KxW_author"
4083
+ };
4084
+ //#endregion
4085
+ //#region src/client/QuoteComposer.tsx
4086
+ /**
4087
+ * The two composer-side pieces of a reply: the button that starts one and the bar that shows
4088
+ * the message being answered.
4089
+ *
4090
+ * Both are seats on official composers, and both are deliberately dumb: they read a pending
4091
+ * quote from the store and call back into it. Nothing here sends a message — the quote reaches
4092
+ * the room because `MessageSide` attaches it when the reply is submitted, and keeping that
4093
+ * decision in one place is why these two do not also try to.
4094
+ *
4095
+ * @module @sparkelf/dsh-group-chat/client/QuoteComposer
4096
+ */
4097
+ /**
4098
+ * The bar above the composer showing what the reply answers.
4099
+ *
4100
+ * Sits in the composer's own stack rather than over the input, so the text the reader types is
4101
+ * never covered by it. Absent when nothing is being answered, which is the common case.
4102
+ */
4103
+ const PendingQuoteBar = (props) => {
4104
+ const { t, quotes, store } = props;
4105
+ const roomId = (0, react.useSyncExternalStore)(store.subscribe, () => store.getState().activeRoomId, () => store.getState().activeRoomId);
4106
+ const read = () => roomId === void 0 ? void 0 : quotes.getQuote(roomId);
4107
+ const quote = (0, react.useSyncExternalStore)(quotes.subscribe, read, read);
4108
+ if (roomId === void 0 || quote === void 0) return null;
4109
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4110
+ className: QuoteComposer_module_css_default.bar,
4111
+ "data-group-chat-pending-quote": quote.messageId,
4112
+ children: [
4113
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4114
+ className: QuoteComposer_module_css_default.mark,
4115
+ "aria-hidden": "true"
4116
+ }),
4117
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4118
+ className: QuoteComposer_module_css_default.body,
4119
+ children: [quote.authorName === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4120
+ className: QuoteComposer_module_css_default.author,
4121
+ children: quote.authorName
4122
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4123
+ className: QuoteComposer_module_css_default.text,
4124
+ children: quote.preview
4125
+ })]
4126
+ }),
4127
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4128
+ type: "button",
4129
+ className: QuoteComposer_module_css_default.dismiss,
4130
+ "aria-label": t("replyCancel"),
4131
+ title: t("replyCancel"),
4132
+ onClick: () => {
4133
+ quotes.clear(roomId);
4134
+ },
4135
+ children: "×"
4136
+ })
4137
+ ]
4138
+ });
4139
+ };
4140
+ //#endregion
4141
+ //#region src/client/messageReference.ts
4142
+ /**
4143
+ * Room messages as `@` references in the composer.
4144
+ *
4145
+ * Registering a trigger source is the one supported way a plugin adds something to the `@`
4146
+ * menu, and the only way to get an official inline reference: the pipeline turns a pick into
4147
+ * an atomic chip, and the codec decides what that chip becomes for the model. Drawing a
4148
+ * separate quote bar would mean a second, unofficial representation of the same idea.
4149
+ *
4150
+ * A chip carries an id; the words are resolved through this module's cache because the codec
4151
+ * only ever receives `ref`. The cache is bounded to the messages listed most recently, which
4152
+ * is the same window the menu offers.
4153
+ *
4154
+ * @module @sparkelf/dsh-group-chat/client/messageReference
4155
+ */
4156
+ /** Unique source name; duplicate `(trigger, name)` pairs throw at registration. */
4157
+ const SOURCE_NAME = "@sparkelf/dsh-group-chat/message";
4158
+ /** How many messages the menu offers at once. */
4159
+ const MAX_CANDIDATES = 20;
4160
+ /** How much of a message the menu row and the chip label show. */
4161
+ const LABEL_CHARS = 28;
4162
+ /**
4163
+ * Reference id → what it points at.
4164
+ *
4165
+ * `ref` is `${roomId}:${messageId}` so it stays readable in storage and unique across rooms;
4166
+ * the words ride beside it because the codec is synchronous about identity and only receives
4167
+ * the id.
4168
+ */
4169
+ const resolved = /* @__PURE__ */ new Map();
4170
+ /** The text of a message body, whether it arrived as blocks or as one plain string. */
4171
+ const textOf = (content) => {
4172
+ if (typeof content === "string") return content.replace(/\s+/g, " ").trim();
4173
+ if (!Array.isArray(content)) return "";
4174
+ const parts = [];
4175
+ for (const block of content) {
4176
+ if (typeof block !== "object" || block === null) continue;
4177
+ const record = block;
4178
+ if (record.type === "text" && typeof record.text === "string") parts.push(record.text);
4179
+ }
4180
+ return parts.join(" ").replace(/\s+/g, " ").trim();
4181
+ };
4182
+ /** One line, cut to `LABEL_CHARS` with an ellipsis. */
4183
+ const shorten = (text) => text.length > LABEL_CHARS ? `${text.slice(0, 27)}…` : text;
4184
+ /** What one message row shows and what a pick would insert. */
4185
+ const rowOf = (roomId, record) => {
4186
+ const data = record.event.data;
4187
+ if (data === void 0) return void 0;
4188
+ const source = data["source"];
4189
+ const rowId = typeof source?.messageId === "string" && source.messageId.length > 0 ? source.messageId : typeof data["id"] === "string" ? data["id"] : record.id;
4190
+ const text = textOf(data["content"]);
4191
+ if (text.length === 0) return void 0;
4192
+ const authorName = typeof source?.memberName === "string" && source.memberName.length > 0 ? source.memberName : void 0;
4193
+ const label = `${authorName ?? "消息"}:${shorten(text)}`;
4194
+ return {
4195
+ ref: `${roomId}:${rowId}`,
4196
+ name: label,
4197
+ description: text.length > 60 ? `${text.slice(0, 59)}…` : text,
4198
+ resolved: {
4199
+ label,
4200
+ text,
4201
+ ...authorName === void 0 ? {} : { authorName }
4202
+ }
4203
+ };
4204
+ };
4205
+ /**
4206
+ * Registers the room-message reference source.
4207
+ *
4208
+ * @param inputTriggers - the trigger pipeline service (`ctx.get('inputTriggers')`).
4209
+ * @param store - room store, read for the room the composer is writing into.
4210
+ * @returns the disposer.
4211
+ */
4212
+ const registerMessageSource = (inputTriggers, store) => {
4213
+ const source = {
4214
+ trigger: "@",
4215
+ name: SOURCE_NAME,
4216
+ order: 30,
4217
+ showGroupTitle: true,
4218
+ async candidates(_session, request) {
4219
+ const roomId = store.getState().activeRoomId;
4220
+ if (roomId === void 0) return [];
4221
+ const page = await listEvents(roomId);
4222
+ const needle = request.query.trim().toLowerCase();
4223
+ const out = [];
4224
+ for (const record of [...page.events].reverse()) {
4225
+ if (request.signal.aborted) break;
4226
+ const row = rowOf(roomId, record);
4227
+ if (row === void 0) continue;
4228
+ if (needle.length > 0 && !row.resolved.text.toLowerCase().includes(needle)) continue;
4229
+ resolved.set(row.ref, row.resolved);
4230
+ out.push({
4231
+ name: row.name,
4232
+ label: row.name,
4233
+ description: row.description,
4234
+ icon: "session",
4235
+ value: row.ref
4236
+ });
4237
+ if (out.length >= MAX_CANDIDATES) break;
4238
+ }
4239
+ return out;
4240
+ },
4241
+ onPick(pick) {
4242
+ const ref = pick.candidate.value;
4243
+ if (ref === void 0) return void 0;
4244
+ const found = resolved.get(ref);
4245
+ if (found === void 0) return void 0;
4246
+ return { insert: {
4247
+ source: SOURCE_NAME,
4248
+ ref,
4249
+ label: found.label,
4250
+ appearance: "session",
4251
+ clipboardText: `@${found.label}`
4252
+ } };
4253
+ },
4254
+ codec: {
4255
+ clipboardText: (ref) => {
4256
+ const found = resolved.get(ref);
4257
+ return found === void 0 ? ref : `@${found.label}`;
4258
+ },
4259
+ serialize: (ref) => {
4260
+ const found = resolved.get(ref);
4261
+ if (found === void 0) return Promise.resolve(ref);
4262
+ const speaker = found.authorName === void 0 ? "" : `${found.authorName}:`;
4263
+ return Promise.resolve(`> ${speaker}${found.text}`);
4264
+ }
4265
+ }
4266
+ };
4267
+ return inputTriggers.registerSource(source);
4268
+ };
4269
+ //#endregion
3683
4270
  //#region src/client/locales.ts
3684
4271
  /**
3685
4272
  * Group-chat copy, in the shape every locale-backed DSH client plugin uses: one
@@ -3700,7 +4287,7 @@ window.__ModuleLoader__.load({
3700
4287
  roomName: "Room name",
3701
4288
  create: "Create",
3702
4289
  search: "Search rooms",
3703
- searchPlaceholder: "Search rooms…",
4290
+ searchPlaceholder: "Search rooms or messages…",
3704
4291
  searchClear: "Clear search",
3705
4292
  searchEmpty: "No room matches",
3706
4293
  discoverHeading: "Rooms you can join",
@@ -3782,6 +4369,12 @@ window.__ModuleLoader__.load({
3782
4369
  membersFileUpload: "Upload a file",
3783
4370
  membersFileUploadFailed: "Upload failed.",
3784
4371
  resizeRegion: "Resize the group chat region",
4372
+ reply: "Reply",
4373
+ replyCancel: "Cancel reply",
4374
+ searchMessages: "Search messages",
4375
+ searchMessagesPlaceholder: "Search message text",
4376
+ searchMessagesEmpty: "No message matches",
4377
+ searching: "Searching…",
3785
4378
  membersFilesRoot: "Files",
3786
4379
  membersOwner: "Owner",
3787
4380
  membersNotARoom: "This conversation is not a group chat, so it has no members.",
@@ -3845,7 +4438,7 @@ window.__ModuleLoader__.load({
3845
4438
  roomName: "群聊名称",
3846
4439
  create: "创建",
3847
4440
  search: "搜索群聊",
3848
- searchPlaceholder: "搜索群聊…",
4441
+ searchPlaceholder: "搜索群聊或消息…",
3849
4442
  searchClear: "清除搜索",
3850
4443
  searchEmpty: "无匹配结果",
3851
4444
  discoverHeading: "可以加入的群聊",
@@ -3926,6 +4519,12 @@ window.__ModuleLoader__.load({
3926
4519
  membersFileUpload: "上传文件",
3927
4520
  membersFileUploadFailed: "上传失败。",
3928
4521
  resizeRegion: "拖动调节群聊区域高度",
4522
+ reply: "引用",
4523
+ replyCancel: "取消引用",
4524
+ searchMessages: "搜索消息",
4525
+ searchMessagesPlaceholder: "搜索消息内容",
4526
+ searchMessagesEmpty: "没有匹配的消息",
4527
+ searching: "搜索中…",
3929
4528
  membersFilesRoot: "群文件",
3930
4529
  membersOwner: "群主",
3931
4530
  membersNotARoom: "该会话不是群聊,没有群成员。",
@@ -4031,6 +4630,8 @@ window.__ModuleLoader__.load({
4031
4630
  * is keyed by id — the same split the official schedule plugin makes.
4032
4631
  */
4033
4632
  const MEMBERS_TAB_ID = "@sparkelf/dsh-group-chat/members";
4633
+ /** Id of the pending-reply bar in the composer's dock. */
4634
+ const QUOTE_DOCK_ID = "@sparkelf/dsh-group-chat/quote";
4034
4635
  /**
4035
4636
  * The guide entry's own identity, and where it sorts on the start page.
4036
4637
  *
@@ -4060,6 +4661,41 @@ window.__ModuleLoader__.load({
4060
4661
  const t = ctx.locale.bind(NS);
4061
4662
  const tPreset = ctx.locale.bind(PRESET_LOCALE_NS);
4062
4663
  const base = createRoomStore();
4664
+ const quotes = createQuoteStore();
4665
+ /**
4666
+ * Drops the pending reply once the composer submits.
4667
+ *
4668
+ * The composer belongs to the official chat surface, so there is no submit callback to hook.
4669
+ * What is stable is how a submission looks: Enter inside the editor, or a click on the send
4670
+ * button. Both are observed at the document in the capture phase — before the official handler
4671
+ * runs — and this side's pending reply is dropped for the open room. Only the local copy goes:
4672
+ * the host still needs its own to attach the quote to the message being published, and deleting
4673
+ * it here would send the reply bare.
4674
+ */
4675
+ const dropQuoteOnSubmit = () => {
4676
+ const clearActive = () => {
4677
+ const roomId = store.getState().activeRoomId;
4678
+ if (roomId !== void 0) quotes.clearLocal(roomId);
4679
+ };
4680
+ const onSubmitKey = (event) => {
4681
+ if (event.key !== "Enter" || event.shiftKey || event.isComposing) return;
4682
+ const target = event.target;
4683
+ if (target instanceof Element && target.closest("[contenteditable=\"true\"]") !== null) clearActive();
4684
+ };
4685
+ const onSubmitClick = (event) => {
4686
+ const target = event.target;
4687
+ if (!(target instanceof Element)) return;
4688
+ const label = target.closest("button[aria-label]")?.getAttribute("aria-label") ?? "";
4689
+ if (/发送|send/i.test(label)) clearActive();
4690
+ };
4691
+ document.addEventListener("keydown", onSubmitKey, true);
4692
+ document.addEventListener("click", onSubmitClick, true);
4693
+ return () => {
4694
+ document.removeEventListener("keydown", onSubmitKey, true);
4695
+ document.removeEventListener("click", onSubmitClick, true);
4696
+ };
4697
+ };
4698
+ ctx.effect(dropQuoteOnSubmit);
4063
4699
  const store = {
4064
4700
  ...base,
4065
4701
  open: (roomId) => {
@@ -4212,7 +4848,9 @@ window.__ModuleLoader__.load({
4212
4848
  getSelfId: store.selfId,
4213
4849
  subscribeSelf: store.subscribe,
4214
4850
  getRoster: (roomId) => store.getState().members[roomId],
4215
- sided: props["node"] !== void 0
4851
+ sided: props["node"] !== void 0,
4852
+ quotes,
4853
+ tOwn: t
4216
4854
  }));
4217
4855
  } catch (error) {
4218
4856
  logClaimFailure(key, error);
@@ -4227,6 +4865,18 @@ window.__ModuleLoader__.load({
4227
4865
  release();
4228
4866
  };
4229
4867
  });
4868
+ const inputTriggers = ctx.get("inputTriggers");
4869
+ if (inputTriggers !== void 0) ctx.effect(() => registerMessageSource(inputTriggers, store));
4870
+ ctx.effect(() => ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({
4871
+ name: "conversation.input.dock",
4872
+ id: QUOTE_DOCK_ID,
4873
+ locale: NS,
4874
+ inject: (() => ({
4875
+ t,
4876
+ quotes,
4877
+ store
4878
+ }))
4879
+ }, PendingQuoteBar)), "group-chat: pending quote bar");
4230
4880
  }
4231
4881
  //#endregion
4232
4882
  exports.apply = apply;