@sparkelf/dsh-group-chat 0.5.2 → 0.5.4

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
@@ -513,11 +513,11 @@ window.__ModuleLoader__.load({
513
513
  document.head.appendChild(tag);
514
514
  }
515
515
  var Avatar_module_css_default = {
516
- "stack": "Ohch6W_stack",
517
- "avatar": "Ohch6W_avatar",
516
+ "over": "Ohch6W_over",
518
517
  "md": "Ohch6W_md",
519
518
  "sm": "Ohch6W_sm",
520
- "over": "Ohch6W_over"
519
+ "avatar": "Ohch6W_avatar",
520
+ "stack": "Ohch6W_stack"
521
521
  };
522
522
  //#endregion
523
523
  //#region src/client/Avatar.tsx
@@ -557,13 +557,13 @@ window.__ModuleLoader__.load({
557
557
  document.head.appendChild(tag);
558
558
  }
559
559
  var Picker_module_css_default = {
560
+ "row": "sKjJ-a_row",
561
+ "note": "sKjJ-a_note",
562
+ "list": "sKjJ-a_list",
560
563
  "rowActive": "sKjJ-a_rowActive",
561
564
  "box": "sKjJ-a_box",
562
565
  "label": "sKjJ-a_label",
563
- "secondary": "sKjJ-a_secondary",
564
- "list": "sKjJ-a_list",
565
- "note": "sKjJ-a_note",
566
- "row": "sKjJ-a_row"
566
+ "secondary": "sKjJ-a_secondary"
567
567
  };
568
568
  //#endregion
569
569
  //#region src/client/Picker.tsx
@@ -736,11 +736,11 @@ window.__ModuleLoader__.load({
736
736
  document.head.appendChild(tag);
737
737
  }
738
738
  var PresetSelect_module_css_default = {
739
- "trigger": "xjnmxG_trigger",
740
- "name": "xjnmxG_name",
741
- "description": "xjnmxG_description",
742
739
  "row": "xjnmxG_row",
743
- "triggerLabel": "xjnmxG_triggerLabel"
740
+ "description": "xjnmxG_description",
741
+ "triggerLabel": "xjnmxG_triggerLabel",
742
+ "trigger": "xjnmxG_trigger",
743
+ "name": "xjnmxG_name"
744
744
  };
745
745
  //#endregion
746
746
  //#region src/client/PresetSelect.tsx
@@ -828,6 +828,36 @@ window.__ModuleLoader__.load({
828
828
  });
829
829
  };
830
830
  //#endregion
831
+ //#region src/session-id.ts
832
+ /**
833
+ * The room/session binding, shared by both halves of the plugin.
834
+ *
835
+ * The browser half needs it to open a room's Session; the host half needs it to create and
836
+ * recognize one. It lives in its own module because the two halves are built for different
837
+ * runtimes: importing it from the host entry would drag the whole server side into the client
838
+ * bundle, which the build's platform guard refuses — correctly, since none of it can run there.
839
+ *
840
+ * @module @sparkelf/dsh-group-chat/session-id
841
+ */
842
+ /**
843
+ * Every room session id starts with this, so a room's session is recognizable after a restart
844
+ * and an ordinary session never matches.
845
+ *
846
+ * The binding lives in the id rather than in `SessionHeader` because the header carries no
847
+ * free-form metadata field.
848
+ */
849
+ const ROOM_SESSION_PREFIX = "group-room-";
850
+ /** Deterministic session id for a room. */
851
+ const roomSessionId = (roomId) => `${ROOM_SESSION_PREFIX}${roomId}`;
852
+ /** Reads the room a session is bound to, or `undefined` for an ordinary session. */
853
+ const roomIdOfSession = (session) => {
854
+ if (typeof session !== "object" || session === null) return void 0;
855
+ const id = session.id;
856
+ if (typeof id !== "string" || !id.startsWith("group-room-")) return void 0;
857
+ const roomId = id.slice(11);
858
+ return roomId.length > 0 ? roomId : void 0;
859
+ };
860
+ //#endregion
831
861
  //#region src/client/store.ts
832
862
  /**
833
863
  * The room list both client surfaces read.
@@ -842,16 +872,12 @@ window.__ModuleLoader__.load({
842
872
  *
843
873
  * @module @sparkelf/dsh-group-chat/client/store
844
874
  */
845
- /**
846
- * Create the shared store.
847
- * @returns a store whose `getState` returns a stable reference between changes, which is
848
- * what `useSyncExternalStore` requires to avoid a render loop.
849
- */
850
- function createRoomStore() {
875
+ function createRoomStore(deps = {}) {
851
876
  let state = {
852
877
  rooms: void 0,
853
878
  activeRoomId: void 0,
854
879
  failure: void 0,
880
+ openFailure: void 0,
855
881
  searchQuery: "",
856
882
  selfId: void 0,
857
883
  administrator: false,
@@ -918,6 +944,7 @@ window.__ModuleLoader__.load({
918
944
  open: (roomId) => {
919
945
  set({
920
946
  activeRoomId: roomId,
947
+ openFailure: void 0,
921
948
  ...state.rooms === void 0 ? {} : { rooms: state.rooms.map((room) => room.id === roomId ? {
922
949
  ...room,
923
950
  unreadCount: 0,
@@ -925,6 +952,13 @@ window.__ModuleLoader__.load({
925
952
  } : room) }
926
953
  });
927
954
  loadMembersInto(roomId);
955
+ const sessionId = roomSessionId(roomId);
956
+ try {
957
+ deps.openSession?.(sessionId);
958
+ } catch (error) {
959
+ console.error("[group-chat] selecting the room session failed", sessionId, error);
960
+ set({ openFailure: "roomOpenFailed" });
961
+ }
928
962
  },
929
963
  discover: async (query) => {
930
964
  try {
@@ -1005,23 +1039,23 @@ window.__ModuleLoader__.load({
1005
1039
  document.head.appendChild(tag);
1006
1040
  }
1007
1041
  var CreateRoomDialog_module_css_default = {
1008
- "field": "Z3w8WW_field",
1042
+ "memberName": "Z3w8WW_memberName",
1043
+ "body": "Z3w8WW_body",
1044
+ "memberBadge": "Z3w8WW_memberBadge",
1045
+ "label": "Z3w8WW_label",
1046
+ "error": "Z3w8WW_error",
1047
+ "pill": "Z3w8WW_pill",
1048
+ "memberList": "Z3w8WW_memberList",
1009
1049
  "footer": "Z3w8WW_footer",
1010
- "triggerExtra": "Z3w8WW_triggerExtra",
1050
+ "switches": "Z3w8WW_switches",
1011
1051
  "policyRow": "Z3w8WW_policyRow",
1012
- "pillActive": "Z3w8WW_pillActive",
1013
- "memberRow": "Z3w8WW_memberRow",
1014
- "memberList": "Z3w8WW_memberList",
1015
1052
  "warn": "Z3w8WW_warn",
1016
- "notice": "Z3w8WW_notice",
1017
- "pill": "Z3w8WW_pill",
1018
- "error": "Z3w8WW_error",
1019
- "label": "Z3w8WW_label",
1020
- "body": "Z3w8WW_body",
1021
- "switches": "Z3w8WW_switches",
1053
+ "field": "Z3w8WW_field",
1022
1054
  "hint": "Z3w8WW_hint",
1023
- "memberName": "Z3w8WW_memberName",
1024
- "memberBadge": "Z3w8WW_memberBadge"
1055
+ "pillActive": "Z3w8WW_pillActive",
1056
+ "notice": "Z3w8WW_notice",
1057
+ "memberRow": "Z3w8WW_memberRow",
1058
+ "triggerExtra": "Z3w8WW_triggerExtra"
1025
1059
  };
1026
1060
  //#endregion
1027
1061
  //#region src/client/CreateRoomDialog.tsx
@@ -1288,28 +1322,28 @@ window.__ModuleLoader__.load({
1288
1322
  document.head.appendChild(tag);
1289
1323
  }
1290
1324
  var InviteDialog_module_css_default = {
1291
- "chip": "r4uCba_chip",
1292
1325
  "rowHandle": "r4uCba_rowHandle",
1293
- "searchRow": "r4uCba_searchRow",
1294
- "chipName": "r4uCba_chipName",
1295
- "row": "r4uCba_row",
1296
- "field": "r4uCba_field",
1297
- "chips": "r4uCba_chips",
1298
- "note": "r4uCba_note",
1299
1326
  "error": "r4uCba_error",
1300
- "check": "r4uCba_check",
1301
1327
  "inviteSpin": "r4uCba_inviteSpin",
1302
- "content": "r4uCba_content",
1303
1328
  "search": "r4uCba_search",
1304
- "visuallyHidden": "r4uCba_visuallyHidden",
1305
- "spinner": "r4uCba_spinner",
1306
1329
  "dialog": "r4uCba_dialog",
1307
- "checkHidden": "r4uCba_checkHidden",
1308
- "errorRow": "r4uCba_errorRow",
1330
+ "row": "r4uCba_row",
1331
+ "rowSelected": "r4uCba_rowSelected",
1332
+ "check": "r4uCba_check",
1309
1333
  "chipRemove": "r4uCba_chipRemove",
1334
+ "errorRow": "r4uCba_errorRow",
1335
+ "spinner": "r4uCba_spinner",
1336
+ "list": "r4uCba_list",
1337
+ "field": "r4uCba_field",
1338
+ "note": "r4uCba_note",
1339
+ "content": "r4uCba_content",
1340
+ "chips": "r4uCba_chips",
1341
+ "chip": "r4uCba_chip",
1342
+ "chipName": "r4uCba_chipName",
1343
+ "checkHidden": "r4uCba_checkHidden",
1344
+ "visuallyHidden": "r4uCba_visuallyHidden",
1310
1345
  "rowName": "r4uCba_rowName",
1311
- "rowSelected": "r4uCba_rowSelected",
1312
- "list": "r4uCba_list"
1346
+ "searchRow": "r4uCba_searchRow"
1313
1347
  };
1314
1348
  //#endregion
1315
1349
  //#region src/client/RoomDialogs.tsx
@@ -1926,67 +1960,67 @@ window.__ModuleLoader__.load({
1926
1960
  document.head.appendChild(tag);
1927
1961
  }
1928
1962
  var SidebarRooms_module_css_default = {
1929
- "discoverMeta": "s0QgKq_discoverMeta",
1930
- "root": "s0QgKq_root",
1931
- "joinButton": "s0QgKq_joinButton",
1932
- "sectionHeader": "s0QgKq_sectionHeader",
1933
- "menuHeading": "s0QgKq_menuHeading",
1934
- "discoverHeading": "s0QgKq_discoverHeading",
1935
- "railButton": "s0QgKq_railButton",
1936
- "searchButton": "s0QgKq_searchButton",
1937
- "searchExpanded": "s0QgKq_searchExpanded",
1938
- "check": "s0QgKq_check",
1939
- "rowWrap": "s0QgKq_rowWrap",
1940
- "leaveConfirmDanger": "s0QgKq_leaveConfirmDanger",
1941
- "menu": "s0QgKq_menu",
1942
- "hit": "s0QgKq_hit",
1943
- "discoverName": "s0QgKq_discoverName",
1944
- "fade": "s0QgKq_fade",
1963
+ "empty": "s0QgKq_empty",
1964
+ "leaveCopy": "s0QgKq_leaveCopy",
1945
1965
  "flatList": "s0QgKq_flatList",
1946
- "searchSlotExpanded": "s0QgKq_searchSlotExpanded",
1947
- "hitAuthor": "s0QgKq_hitAuthor",
1948
- "menuItem": "s0QgKq_menuItem",
1949
- "time": "s0QgKq_time",
1950
- "unread": "s0QgKq_unread",
1951
- "viewWrap": "s0QgKq_viewWrap",
1952
- "list": "s0QgKq_list",
1953
1966
  "menuLayer": "s0QgKq_menuLayer",
1954
- "menuConfirm": "s0QgKq_menuConfirm",
1955
- "headerActions": "s0QgKq_headerActions",
1956
- "visuallyHidden": "s0QgKq_visuallyHidden",
1957
- "unreadMentioned": "s0QgKq_unreadMentioned",
1958
- "leaveRoomName": "s0QgKq_leaveRoomName",
1959
- "iconButton": "s0QgKq_iconButton",
1960
- "mark": "s0QgKq_mark",
1961
- "sessionRowSelected": "s0QgKq_sessionRowSelected",
1962
- "discoverSection": "s0QgKq_discoverSection",
1967
+ "menuRename": "s0QgKq_menuRename",
1968
+ "discoverMeta": "s0QgKq_discoverMeta",
1969
+ "menuInput": "s0QgKq_menuInput",
1970
+ "hitRoom": "s0QgKq_hitRoom",
1971
+ "searchInput": "s0QgKq_searchInput",
1972
+ "discoverName": "s0QgKq_discoverName",
1973
+ "search": "s0QgKq_search",
1963
1974
  "clearButton": "s0QgKq_clearButton",
1964
- "menuCancel": "s0QgKq_menuCancel",
1965
- "footer": "s0QgKq_footer",
1966
1975
  "rowIcon": "s0QgKq_rowIcon",
1967
1976
  "emptyState": "s0QgKq_emptyState",
1977
+ "menu": "s0QgKq_menu",
1968
1978
  "leaveError": "s0QgKq_leaveError",
1969
- "title": "s0QgKq_title",
1970
- "hitRoom": "s0QgKq_hitRoom",
1971
- "resizer": "s0QgKq_resizer",
1972
1979
  "sectionLabel": "s0QgKq_sectionLabel",
1973
- "menuRename": "s0QgKq_menuRename",
1980
+ "fade": "s0QgKq_fade",
1981
+ "unread": "s0QgKq_unread",
1982
+ "viewWrap": "s0QgKq_viewWrap",
1974
1983
  "sessionRow": "s0QgKq_sessionRow",
1984
+ "menuHeading": "s0QgKq_menuHeading",
1985
+ "discoverSection": "s0QgKq_discoverSection",
1986
+ "mark": "s0QgKq_mark",
1987
+ "unreadMentioned": "s0QgKq_unreadMentioned",
1988
+ "iconButton": "s0QgKq_iconButton",
1989
+ "root": "s0QgKq_root",
1990
+ "list": "s0QgKq_list",
1991
+ "joinButton": "s0QgKq_joinButton",
1992
+ "hitAuthor": "s0QgKq_hitAuthor",
1993
+ "searchExpanded": "s0QgKq_searchExpanded",
1994
+ "sessionRowSelected": "s0QgKq_sessionRowSelected",
1995
+ "headerActions": "s0QgKq_headerActions",
1996
+ "hit": "s0QgKq_hit",
1975
1997
  "searchSlot": "s0QgKq_searchSlot",
1976
- "menuInput": "s0QgKq_menuInput",
1977
- "searchInput": "s0QgKq_searchInput",
1998
+ "check": "s0QgKq_check",
1999
+ "discoverHeading": "s0QgKq_discoverHeading",
2000
+ "menuCancel": "s0QgKq_menuCancel",
2001
+ "leaveConfirmDanger": "s0QgKq_leaveConfirmDanger",
1978
2002
  "hitText": "s0QgKq_hitText",
1979
- "menuInline": "s0QgKq_menuInline",
1980
- "hitList": "s0QgKq_hitList",
2003
+ "footer": "s0QgKq_footer",
2004
+ "visuallyHidden": "s0QgKq_visuallyHidden",
2005
+ "leaveRoomName": "s0QgKq_leaveRoomName",
2006
+ "menuItem": "s0QgKq_menuItem",
2007
+ "railButton": "s0QgKq_railButton",
1981
2008
  "menuActions": "s0QgKq_menuActions",
1982
- "leaveCopy": "s0QgKq_leaveCopy",
2009
+ "menuInline": "s0QgKq_menuInline",
2010
+ "rowWrap": "s0QgKq_rowWrap",
2011
+ "searchButton": "s0QgKq_searchButton",
1983
2012
  "listArea": "s0QgKq_listArea",
1984
- "hitHead": "s0QgKq_hitHead",
1985
- "search": "s0QgKq_search",
2013
+ "menuConfirm": "s0QgKq_menuConfirm",
1986
2014
  "discoverRow": "s0QgKq_discoverRow",
2015
+ "resizer": "s0QgKq_resizer",
2016
+ "hitHead": "s0QgKq_hitHead",
2017
+ "hitList": "s0QgKq_hitList",
1987
2018
  "leaveBody": "s0QgKq_leaveBody",
1988
2019
  "hitHint": "s0QgKq_hitHint",
1989
- "empty": "s0QgKq_empty"
2020
+ "searchSlotExpanded": "s0QgKq_searchSlotExpanded",
2021
+ "title": "s0QgKq_title",
2022
+ "time": "s0QgKq_time",
2023
+ "sectionHeader": "s0QgKq_sectionHeader"
1990
2024
  };
1991
2025
  //#endregion
1992
2026
  //#region src/client/SidebarRooms.tsx
@@ -2086,7 +2120,7 @@ window.__ModuleLoader__.load({
2086
2120
  }
2087
2121
  });
2088
2122
  }
2089
- const { rooms, activeRoomId, failure, searchQuery, discoverable } = (0, react.useSyncExternalStore)(store.subscribe, store.getState, store.getState);
2123
+ const { rooms, activeRoomId, failure, openFailure, searchQuery, discoverable } = (0, react.useSyncExternalStore)(store.subscribe, store.getState, store.getState);
2090
2124
  const [searchExpanded, setSearchExpanded] = (0, react.useState)(false);
2091
2125
  const [viewOpen, setViewOpen] = (0, react.useState)(false);
2092
2126
  const [orderBy, setOrderBy] = (0, react.useState)("updated");
@@ -2426,6 +2460,11 @@ window.__ModuleLoader__.load({
2426
2460
  className: SidebarRooms_module_css_default.empty,
2427
2461
  children: t(failure)
2428
2462
  }),
2463
+ openFailure !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2464
+ className: SidebarRooms_module_css_default.empty,
2465
+ role: "alert",
2466
+ children: t(openFailure)
2467
+ }),
2429
2468
  failure === void 0 && rooms === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2430
2469
  className: SidebarRooms_module_css_default.empty,
2431
2470
  children: t("loading")
@@ -3079,20 +3118,20 @@ window.__ModuleLoader__.load({
3079
3118
  document.head.appendChild(tag);
3080
3119
  }
3081
3120
  var MessageSide_module_css_default = {
3082
- "rowActionsSelf": "KXabfq_rowActionsSelf",
3083
- "quoteBody": "KXabfq_quoteBody",
3084
- "author": "KXabfq_author",
3085
3121
  "otherRow": "KXabfq_otherRow",
3086
- "selfRow": "KXabfq_selfRow",
3087
- "rowBody": "KXabfq_rowBody",
3088
- "quoteBar": "KXabfq_quoteBar",
3122
+ "quoteText": "KXabfq_quoteText",
3123
+ "quoteAuthor": "KXabfq_quoteAuthor",
3089
3124
  "rowActions": "KXabfq_rowActions",
3125
+ "author": "KXabfq_author",
3090
3126
  "replyButton": "KXabfq_replyButton",
3127
+ "selfRow": "KXabfq_selfRow",
3128
+ "rowBody": "KXabfq_rowBody",
3091
3129
  "selfBody": "KXabfq_selfBody",
3092
- "authorName": "KXabfq_authorName",
3093
- "quoteText": "KXabfq_quoteText",
3094
- "quoteAuthor": "KXabfq_quoteAuthor",
3095
- "quoteMark": "KXabfq_quoteMark"
3130
+ "quoteBar": "KXabfq_quoteBar",
3131
+ "quoteMark": "KXabfq_quoteMark",
3132
+ "rowActionsSelf": "KXabfq_rowActionsSelf",
3133
+ "quoteBody": "KXabfq_quoteBody",
3134
+ "authorName": "KXabfq_authorName"
3096
3135
  };
3097
3136
  //#endregion
3098
3137
  //#region src/client/MessageSide.tsx
@@ -3342,36 +3381,6 @@ window.__ModuleLoader__.load({
3342
3381
  });
3343
3382
  };
3344
3383
  //#endregion
3345
- //#region src/session-id.ts
3346
- /**
3347
- * The room/session binding, shared by both halves of the plugin.
3348
- *
3349
- * The browser half needs it to open a room's Session; the host half needs it to create and
3350
- * recognize one. It lives in its own module because the two halves are built for different
3351
- * runtimes: importing it from the host entry would drag the whole server side into the client
3352
- * bundle, which the build's platform guard refuses — correctly, since none of it can run there.
3353
- *
3354
- * @module @sparkelf/dsh-group-chat/session-id
3355
- */
3356
- /**
3357
- * Every room session id starts with this, so a room's session is recognizable after a restart
3358
- * and an ordinary session never matches.
3359
- *
3360
- * The binding lives in the id rather than in `SessionHeader` because the header carries no
3361
- * free-form metadata field.
3362
- */
3363
- const ROOM_SESSION_PREFIX = "group-room-";
3364
- /** Deterministic session id for a room. */
3365
- const roomSessionId = (roomId) => `${ROOM_SESSION_PREFIX}${roomId}`;
3366
- /** Reads the room a session is bound to, or `undefined` for an ordinary session. */
3367
- const roomIdOfSession = (session) => {
3368
- if (typeof session !== "object" || session === null) return void 0;
3369
- const id = session.id;
3370
- if (typeof id !== "string" || !id.startsWith("group-room-")) return void 0;
3371
- const roomId = id.slice(11);
3372
- return roomId.length > 0 ? roomId : void 0;
3373
- };
3374
- //#endregion
3375
3384
  //#region \0dsh-css:/root/projects/dsh-plugins-plus/packages/group-chat/src/client/MembersPanel.module.css.mjs
3376
3385
  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}";
3377
3386
  const tagId$2 = "@sparkelf/dsh-group-chat/MembersPanel.module.css";
@@ -3383,46 +3392,46 @@ window.__ModuleLoader__.load({
3383
3392
  document.head.appendChild(tag);
3384
3393
  }
3385
3394
  var MembersPanel_module_css_default = {
3386
- "textarea": "VeQVAa_textarea",
3395
+ "linkButton": "VeQVAa_linkButton",
3396
+ "filePicker": "VeQVAa_filePicker",
3397
+ "fileButton": "VeQVAa_fileButton",
3398
+ "crumbGroup": "VeQVAa_crumbGroup",
3399
+ "sectionToggle": "VeQVAa_sectionToggle",
3400
+ "section": "VeQVAa_section",
3401
+ "search": "VeQVAa_search",
3402
+ "sectionBody": "VeQVAa_sectionBody",
3403
+ "crumb": "VeQVAa_crumb",
3404
+ "sectionHeader": "VeQVAa_sectionHeader",
3387
3405
  "previewHeader": "VeQVAa_previewHeader",
3388
- "error": "VeQVAa_error",
3389
- "previewClose": "VeQVAa_previewClose",
3406
+ "refresh": "VeQVAa_refresh",
3390
3407
  "announcementText": "VeQVAa_announcementText",
3391
- "crumb": "VeQVAa_crumb",
3408
+ "fileIcon": "VeQVAa_fileIcon",
3409
+ "previewClose": "VeQVAa_previewClose",
3410
+ "unavailable": "VeQVAa_unavailable",
3411
+ "editorFooter": "VeQVAa_editorFooter",
3412
+ "row": "VeQVAa_row",
3413
+ "crumbs": "VeQVAa_crumbs",
3414
+ "count": "VeQVAa_count",
3415
+ "list": "VeQVAa_list",
3416
+ "root": "VeQVAa_root",
3392
3417
  "searchToggle": "VeQVAa_searchToggle",
3418
+ "textarea": "VeQVAa_textarea",
3419
+ "crumbSep": "VeQVAa_crumbSep",
3420
+ "notice": "VeQVAa_notice",
3393
3421
  "editor": "VeQVAa_editor",
3394
- "sectionToggle": "VeQVAa_sectionToggle",
3395
- "name": "VeQVAa_name",
3422
+ "ownerTag": "VeQVAa_ownerTag",
3396
3423
  "sectionLabel": "VeQVAa_sectionLabel",
3397
- "caret": "VeQVAa_caret",
3398
- "notice": "VeQVAa_notice",
3399
- "row": "VeQVAa_row",
3400
- "refresh": "VeQVAa_refresh",
3401
- "preview": "VeQVAa_preview",
3402
- "previewTitle": "VeQVAa_previewTitle",
3424
+ "previewBody": "VeQVAa_previewBody",
3425
+ "remove": "VeQVAa_remove",
3403
3426
  "fileSize": "VeQVAa_fileSize",
3404
- "search": "VeQVAa_search",
3405
- "crumbGroup": "VeQVAa_crumbGroup",
3406
- "unavailable": "VeQVAa_unavailable",
3407
- "fileIcon": "VeQVAa_fileIcon",
3408
- "previewImage": "VeQVAa_previewImage",
3409
- "list": "VeQVAa_list",
3410
- "filePicker": "VeQVAa_filePicker",
3411
3427
  "hint": "VeQVAa_hint",
3412
- "count": "VeQVAa_count",
3428
+ "caret": "VeQVAa_caret",
3429
+ "previewImage": "VeQVAa_previewImage",
3413
3430
  "selfTag": "VeQVAa_selfTag",
3414
- "section": "VeQVAa_section",
3415
- "previewBody": "VeQVAa_previewBody",
3416
- "crumbSep": "VeQVAa_crumbSep",
3417
- "root": "VeQVAa_root",
3418
- "sectionHeader": "VeQVAa_sectionHeader",
3419
- "editorFooter": "VeQVAa_editorFooter",
3420
- "linkButton": "VeQVAa_linkButton",
3421
- "crumbs": "VeQVAa_crumbs",
3422
- "fileButton": "VeQVAa_fileButton",
3423
- "remove": "VeQVAa_remove",
3424
- "sectionBody": "VeQVAa_sectionBody",
3425
- "ownerTag": "VeQVAa_ownerTag"
3431
+ "name": "VeQVAa_name",
3432
+ "previewTitle": "VeQVAa_previewTitle",
3433
+ "error": "VeQVAa_error",
3434
+ "preview": "VeQVAa_preview"
3426
3435
  };
3427
3436
  //#endregion
3428
3437
  //#region src/client/MembersPanel.tsx
@@ -4046,10 +4055,10 @@ window.__ModuleLoader__.load({
4046
4055
  }
4047
4056
  var GuideEntry_module_css_default = {
4048
4057
  "title": "_0Vnsuq_title",
4049
- "text": "_0Vnsuq_text",
4050
- "icon": "_0Vnsuq_icon",
4051
4058
  "entry": "_0Vnsuq_entry",
4052
- "description": "_0Vnsuq_description"
4059
+ "icon": "_0Vnsuq_icon",
4060
+ "description": "_0Vnsuq_description",
4061
+ "text": "_0Vnsuq_text"
4053
4062
  };
4054
4063
  //#endregion
4055
4064
  //#region src/client/GuideEntry.tsx
@@ -4116,13 +4125,13 @@ window.__ModuleLoader__.load({
4116
4125
  document.head.appendChild(tag);
4117
4126
  }
4118
4127
  var QuoteComposer_module_css_default = {
4128
+ "dismiss": "AK6KxW_dismiss",
4129
+ "button": "AK6KxW_button",
4119
4130
  "author": "AK6KxW_author",
4120
- "bar": "AK6KxW_bar",
4121
- "text": "AK6KxW_text",
4122
4131
  "body": "AK6KxW_body",
4123
- "dismiss": "AK6KxW_dismiss",
4124
4132
  "mark": "AK6KxW_mark",
4125
- "button": "AK6KxW_button"
4133
+ "text": "AK6KxW_text",
4134
+ "bar": "AK6KxW_bar"
4126
4135
  };
4127
4136
  //#endregion
4128
4137
  //#region src/client/QuoteComposer.tsx
@@ -4197,9 +4206,9 @@ window.__ModuleLoader__.load({
4197
4206
  * @module @sparkelf/dsh-group-chat/client/messageReference
4198
4207
  */
4199
4208
  /** Unique source name; duplicate `(trigger, name)` pairs throw at registration. */
4200
- const SOURCE_NAME = "@sparkelf/dsh-group-chat/message";
4209
+ const SOURCE_NAME$1 = "@sparkelf/dsh-group-chat/message";
4201
4210
  /** How many messages the menu offers at once. */
4202
- const MAX_CANDIDATES = 20;
4211
+ const MAX_CANDIDATES$1 = 20;
4203
4212
  /** How much of a message the menu row and the chip label show. */
4204
4213
  const LABEL_CHARS = 28;
4205
4214
  /**
@@ -4255,7 +4264,7 @@ window.__ModuleLoader__.load({
4255
4264
  const registerMessageSource = (inputTriggers, store) => {
4256
4265
  const source = {
4257
4266
  trigger: "@",
4258
- name: SOURCE_NAME,
4267
+ name: SOURCE_NAME$1,
4259
4268
  order: 30,
4260
4269
  showGroupTitle: true,
4261
4270
  async candidates(_session, request) {
@@ -4277,7 +4286,7 @@ window.__ModuleLoader__.load({
4277
4286
  icon: "session",
4278
4287
  value: row.ref
4279
4288
  });
4280
- if (out.length >= MAX_CANDIDATES) break;
4289
+ if (out.length >= MAX_CANDIDATES$1) break;
4281
4290
  }
4282
4291
  return out;
4283
4292
  },
@@ -4287,7 +4296,7 @@ window.__ModuleLoader__.load({
4287
4296
  const found = resolved.get(ref);
4288
4297
  if (found === void 0) return void 0;
4289
4298
  return { insert: {
4290
- source: SOURCE_NAME,
4299
+ source: SOURCE_NAME$1,
4291
4300
  ref,
4292
4301
  label: found.label,
4293
4302
  appearance: "session",
@@ -4310,6 +4319,115 @@ window.__ModuleLoader__.load({
4310
4319
  return inputTriggers.registerSource(source);
4311
4320
  };
4312
4321
  //#endregion
4322
+ //#region src/reference-ids.ts
4323
+ /**
4324
+ * Trigger-source identities shared by both halves of the package.
4325
+ *
4326
+ * The composer declares a mention with the source that produced the chip, and the Host routes
4327
+ * only the ids that source owns, so the string is a contract rather than a label. It lives here
4328
+ * so the client bundle and the host bundle cannot drift apart.
4329
+ *
4330
+ * @module @sparkelf/dsh-group-chat/reference-ids
4331
+ */
4332
+ /** The `@` source whose picks are roster members. */
4333
+ const MEMBER_MENTION_SOURCE = "@sparkelf/dsh-group-chat/member";
4334
+ //#endregion
4335
+ //#region src/client/mentionSource.ts
4336
+ /**
4337
+ * Build the member source for one room.
4338
+ * @param members - the room roster.
4339
+ * @param selfId - the caller's account id, excluded because mentioning yourself is not a way
4340
+ * to notify anyone; the host's self-mention route handles waking the agent separately.
4341
+ * @returns id/name/avatar rows in roster order.
4342
+ */
4343
+ function mentionSourceOf(members, selfId) {
4344
+ return members.filter((member) => member.userId !== selfId).map((member) => ({
4345
+ id: member.userId,
4346
+ displayName: member.displayName.trim() === "" ? member.userId : member.displayName,
4347
+ ...member.avatarUrl === void 0 || member.avatarUrl === null || member.avatarUrl === "" ? {} : { avatarUrl: member.avatarUrl }
4348
+ }));
4349
+ }
4350
+ //#endregion
4351
+ //#region src/client/memberReference.ts
4352
+ /**
4353
+ * Room members as `@` mentions in the composer.
4354
+ *
4355
+ * The `@` menu is a multi-source pipeline: every source owns one group, and a pick becomes an
4356
+ * official inline chip. A member is picked the same way a room message is, but the chip declares
4357
+ * itself with `appearance: 'mention'`, which is what makes the composer hand the picked ids to the
4358
+ * Host as `prompt.mentions` instead of leaving them to be re-parsed out of the prompt text. The
4359
+ * Host's routing reads ids by design ("never parsed out of message text"): text parsing would
4360
+ * misread a code sample containing `@` and would let any message smuggle itself into an execution
4361
+ * path.
4362
+ *
4363
+ * The group appears only in a room: `candidates` answers an empty list everywhere else, and an
4364
+ * empty group closes itself, so a normal session's `@` menu is unchanged.
4365
+ *
4366
+ * @module @sparkelf/dsh-group-chat/client/memberReference
4367
+ */
4368
+ /** Unique source name; duplicate `(trigger, name)` pairs throw at registration. */
4369
+ const SOURCE_NAME = MEMBER_MENTION_SOURCE;
4370
+ /** How many members the menu offers at once. */
4371
+ const MAX_CANDIDATES = 20;
4372
+ /** Reference id → the display name the chip and the clipboard need. */
4373
+ const names = /* @__PURE__ */ new Map();
4374
+ /**
4375
+ * Registers the room-member mention source.
4376
+ *
4377
+ * @param inputTriggers - the trigger pipeline service (`ctx.get('inputTriggers')`).
4378
+ * @param store - room store, read for the room the composer is writing into.
4379
+ * @returns the disposer.
4380
+ */
4381
+ const registerMemberSource = (inputTriggers, store) => {
4382
+ const source = {
4383
+ trigger: "@",
4384
+ name: SOURCE_NAME,
4385
+ order: 20,
4386
+ showGroupTitle: true,
4387
+ async candidates(_session, request) {
4388
+ const roomId = store.getState().activeRoomId;
4389
+ if (roomId === void 0) return [];
4390
+ const members = await listMembers(roomId);
4391
+ const roster = mentionSourceOf(members);
4392
+ const owners = new Set(members.filter((member) => member.owner).map((member) => member.userId));
4393
+ const needle = request.query.trim().toLowerCase();
4394
+ const out = [];
4395
+ for (const member of roster) {
4396
+ if (request.signal.aborted) break;
4397
+ if (needle.length > 0 && !member.displayName.toLowerCase().includes(needle)) continue;
4398
+ names.set(member.id, member.displayName);
4399
+ out.push({
4400
+ name: member.displayName,
4401
+ ...owners.has(member.id) ? { description: "群主" } : {},
4402
+ icon: "mention",
4403
+ value: member.id
4404
+ });
4405
+ if (out.length >= MAX_CANDIDATES) break;
4406
+ }
4407
+ return out;
4408
+ },
4409
+ onPick(pick) {
4410
+ const memberId = pick.candidate.value;
4411
+ if (memberId === void 0) return void 0;
4412
+ const name = names.get(memberId) ?? pick.candidate.name;
4413
+ return { insert: {
4414
+ source: SOURCE_NAME,
4415
+ ref: memberId,
4416
+ label: name,
4417
+ appearance: "mention",
4418
+ clipboardText: `@${name}`
4419
+ } };
4420
+ },
4421
+ codec: {
4422
+ /** What lands in the draft and the clipboard: the human-facing mention. */
4423
+ clipboardText: (ref) => `@${names.get(ref) ?? ref}`,
4424
+ /** What the model reads in place of the chip. The id rides the prompt's `mentions`. */
4425
+ serialize: (ref) => Promise.resolve(`@${names.get(ref) ?? ref}`)
4426
+ }
4427
+ };
4428
+ return inputTriggers.registerSource(source);
4429
+ };
4430
+ //#endregion
4313
4431
  //#region src/client/locales.ts
4314
4432
  /**
4315
4433
  * Group-chat copy, in the shape every locale-backed DSH client plugin uses: one
@@ -4325,6 +4443,7 @@ window.__ModuleLoader__.load({
4325
4443
  description: "Rooms this workspace has joined. @ yourself to make the agent answer; every other message is recorded and read, but nothing runs.",
4326
4444
  loading: "Loading rooms…",
4327
4445
  retry: "Retry",
4446
+ roomOpenFailed: "Could not open this room. Please retry.",
4328
4447
  emptyRooms: "No rooms yet",
4329
4448
  createRoom: "New room",
4330
4449
  roomName: "Room name",
@@ -4475,6 +4594,7 @@ window.__ModuleLoader__.load({
4475
4594
  title: "群聊",
4476
4595
  description: "本工作区已加入的群聊。@ 自己会触发 agent 应答;其他消息都会记录并进入上下文,但不执行。",
4477
4596
  loading: "正在加载群聊…",
4597
+ roomOpenFailed: "无法打开该房间,请稍后重试。",
4478
4598
  retry: "重试",
4479
4599
  emptyRooms: "暂无群聊",
4480
4600
  createRoom: "新建群聊",
@@ -4690,7 +4810,9 @@ window.__ModuleLoader__.load({
4690
4810
  "uiWorkspace",
4691
4811
  "workspaces",
4692
4812
  "sidebarRightTabs",
4693
- "sidebarRight"
4813
+ "sidebarRight",
4814
+ "sessions",
4815
+ "layout"
4694
4816
  ];
4695
4817
  /**
4696
4818
  * Register the sidebar region and the room page.
@@ -4724,7 +4846,13 @@ window.__ModuleLoader__.load({
4724
4846
  }), "group-chat: copy");
4725
4847
  const t = ctx.locale.bind(NS);
4726
4848
  const tPreset = ctx.locale.bind(PRESET_LOCALE_NS);
4727
- const base = createRoomStore();
4849
+ const navigation = ctx.get("uiWorkspace");
4850
+ if (navigation?.openSession === void 0) console.warn("[group-chat] uiWorkspace.openSession is unavailable; room selection cannot navigate");
4851
+ const layout = ctx.get("layout");
4852
+ const base = createRoomStore({ openSession: (sessionId) => {
4853
+ navigation?.openSession?.(sessionId);
4854
+ layout?.selectPanel?.(null);
4855
+ } });
4728
4856
  const quotes = createQuoteStore();
4729
4857
  /**
4730
4858
  * Drops the pending reply once the composer submits.
@@ -4992,7 +5120,10 @@ window.__ModuleLoader__.load({
4992
5120
  };
4993
5121
  });
4994
5122
  const inputTriggers = ctx.get("inputTriggers");
4995
- if (inputTriggers !== void 0) ctx.effect(() => registerMessageSource(inputTriggers, store));
5123
+ if (inputTriggers !== void 0) {
5124
+ ctx.effect(() => registerMessageSource(inputTriggers, store));
5125
+ ctx.effect(() => registerMemberSource(inputTriggers, store));
5126
+ }
4996
5127
  ctx.effect(() => ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({
4997
5128
  name: "conversation.input.dock",
4998
5129
  id: QUOTE_DOCK_ID,