dsh-xrxs-lingting 0.4.0-dev.49 → 0.4.0-dev.50

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/README.md CHANGED
@@ -98,7 +98,7 @@ LINGTING_XIN_PROBE=1 nohup "/path/to/DSH Desktop Dev.app/Contents/MacOS/DSH Desk
98
98
 
99
99
  ## 客户端兼容性验证
100
100
 
101
- `0.4.0-dev.48` 起不再要求宿主提供旧版补丁的 `layout.business`。标准薪灵客户端通过公开的 `shell.overlay` 插槽显示灵听页面,页面中的「返回聊天」关闭页面;提供业务页扩展的旧宿主仍沿用原入口。
101
+ `0.4.0-dev.48` 起不再要求宿主提供旧版补丁的 `layout.business`。`0.4.0-dev.50` 起,标准薪灵客户端通过渲染器公开的 `[data-slot="conversation"]` 标记,将原有灵听页面挂载到主内容区:保留侧栏,暂时隐藏而不卸载聊天,返回时恢复原聊天和草稿。弹窗、列表、实时转写仍复用原组件;转写面板继续使用 `shell.overlay`。提供业务页扩展的旧宿主仍沿用原入口。
102
102
 
103
103
  发布前除单元测试外,应在构建后对目标薪灵源码运行客户端产物冒烟,验证真实布局对象、公开插槽、页面打开及返回聊天:
104
104
 
@@ -108,3 +108,5 @@ npm run smoke:client -- /path/to/cinlyn-desktop
108
108
  ```
109
109
 
110
110
  该检查不代替安装后对授权、录音、转写和回放的人工验证。
111
+
112
+ 布局回归验证:`node scripts/smoke-layout-browser.mjs <playwright/index.mjs 路径>`,使用 Chrome 无头浏览器运行真实插件产物,验证页面边界、弹窗居中、转写面板层级、窗口缩放与卸载后聊天恢复。使用合成录音状态,不访问业务数据、不采集声音。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-xrxs-lingting",
3
- "version": "0.4.0-dev.49",
3
+ "version": "0.4.0-dev.50",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite --host 127.0.0.1",
@@ -30,7 +30,7 @@ module.exports = __toCommonJS(client_exports);
30
30
  var define_import_meta_env_default = { VITE_XIN_PACKAGED: "1" };
31
31
 
32
32
  // src/plugin/client.tsx
33
- var import_react22 = require("react");
33
+ var import_react23 = require("react");
34
34
 
35
35
  // node_modules/lucide-react/dist/esm/createLucideIcon.js
36
36
  var import_react2 = require("react");
@@ -5419,11 +5419,63 @@ function createBusinessNavigation() {
5419
5419
  };
5420
5420
  }
5421
5421
 
5422
+ // src/plugin/business-surface.tsx
5423
+ var import_react22 = require("react");
5424
+ var import_react_dom = require("react-dom");
5425
+ function mountBusinessSurface(doc) {
5426
+ const conversation = doc.querySelector('[data-slot="conversation"]');
5427
+ const center = conversation?.parentElement;
5428
+ if (!conversation || !center) return null;
5429
+ const target = doc.createElement("section");
5430
+ target.className = "lt-business-surface";
5431
+ target.setAttribute("aria-label", "\u7075\u542C");
5432
+ const display = conversation.style.getPropertyValue("display");
5433
+ const displayPriority = conversation.style.getPropertyPriority("display");
5434
+ const position = center.style.getPropertyValue("position");
5435
+ const positionPriority = center.style.getPropertyPriority("position");
5436
+ const inert = conversation.inert;
5437
+ conversation.style.setProperty("display", "none", "important");
5438
+ conversation.inert = true;
5439
+ center.style.setProperty("position", "relative");
5440
+ center.appendChild(target);
5441
+ let disposed = false;
5442
+ return { target, dispose() {
5443
+ if (disposed) return;
5444
+ disposed = true;
5445
+ target.remove();
5446
+ if (display) conversation.style.setProperty("display", display, displayPriority);
5447
+ else conversation.style.removeProperty("display");
5448
+ conversation.inert = inert;
5449
+ if (position) center.style.setProperty("position", position, positionPriority);
5450
+ else center.style.removeProperty("position");
5451
+ } };
5452
+ }
5453
+ function BusinessSurface({ children }) {
5454
+ const [target, setTarget] = (0, import_react22.useState)(null);
5455
+ (0, import_react22.useLayoutEffect)(() => {
5456
+ let mounted = null;
5457
+ const attach = () => {
5458
+ if (mounted?.target.isConnected) return;
5459
+ mounted?.dispose();
5460
+ mounted = mountBusinessSurface(document);
5461
+ setTarget(mounted?.target ?? null);
5462
+ };
5463
+ attach();
5464
+ const observer = new MutationObserver(attach);
5465
+ observer.observe(document.body, { childList: true, subtree: true });
5466
+ return () => {
5467
+ observer.disconnect();
5468
+ mounted?.dispose();
5469
+ };
5470
+ }, []);
5471
+ return target ? (0, import_react_dom.createPortal)(children, target) : null;
5472
+ }
5473
+
5422
5474
  // src/plugin/embedded.css
5423
5475
  var tag3 = document.createElement("style");
5424
5476
  tag3.dataset.plugin = "dsh-xrxs-lingting";
5425
5477
  tag3.dataset.pluginCss = "dsh-xrxs-lingting/embedded.css";
5426
- tag3.textContent = ".lingting-root { color-scheme: light; }\n/* Host \u9002\u914D\u5C42\u72B6\u6001\u63D0\u793A\uFF08\u6388\u6743/\u8EAB\u4EFD/\u76EE\u7684\u5730\u672A\u5C31\u7EEA\uFF09\uFF1A\u56FA\u5B9A\u9876\u90E8\uFF0C\u53EF\u5173\u95ED\uFF0C\u4E0D\u53C2\u4E0E\u9875\u9762\u5E03\u5C40 */\n.lt-host-notice { position: fixed; top: 12px; left: 50%; transform: translateX(-50%); z-index: 60; display: flex; align-items: center; gap: 12px; max-width: min(680px, calc(100vw - 32px)); padding: 10px 14px; border: 1px solid #e7e0fa; border-radius: 10px; background: #fff; box-shadow: 0 6px 24px rgb(40 28 74 / 16%); color: #605972; font-size: 13px; line-height: 1.5; }\n.lt-host-notice-text { flex: 1; }\n.lt-host-notice-close { flex-shrink: 0; border: 0; background: transparent; color: inherit; font-size: 16px; line-height: 1; padding: 2px 4px; border-radius: 6px; cursor: pointer; }\n.lt-host-notice-close:hover { background: #6650d814; }\n.lt-host-notice-close:focus-visible { outline: 2px solid #6650d8; outline-offset: 2px; }\n/* \u5D4C\u5165\u6A21\u5F0F\u4E0B\u6839\u5143\u7D20\u5373 .app\uFF08lingting-root app \u540C\u5143\u7D20\uFF09\uFF0C\u89C4\u5219\u9700\u7528\u7EC4\u5408\u9009\u62E9\u5668\uFF1B\u4FDD\u7559\u540E\u4EE3\u5F62\u5F0F\u517C\u5BB9\u53CC\u5C42\u5305\u88F9\u7ED3\u6784 */\n.lingting-root[data-embedded] { height: 100%; min-height: 0; container-type: inline-size; }\n.lingting-root[data-embedded].app, .lingting-root[data-embedded] .app { height: 100%; min-height: 0; display: flex; flex-direction: column; overflow: hidden; position: relative; padding-bottom: 0; }\n.lingting-root[data-embedded].app .app-header, .lingting-root[data-embedded] .app-header { height: 66px; flex-shrink: 0; }\n.lingting-root[data-embedded].app .header-inner, .lingting-root[data-embedded] .header-inner { padding: 0 28px; max-width: none; }\n.lingting-root[data-embedded].app .brand-caption, .lingting-root[data-embedded] .brand-caption { display: none; }\n.lingting-root[data-embedded].app .main-content, .lingting-root[data-embedded] .main-content { width: 100%; max-width: none; min-height: 0; flex: 1; overflow: auto; padding: 30px 28px 0; scrollbar-width: thin; }\n\n.lingting-root[data-embedded].app .toast, .lingting-root[data-embedded] .toast { position: absolute; top: 77px; }\n.lingting-root[data-global-status] { flex-shrink: 0; border-top: 1px solid #e7e0fa; background: white; padding: 0 24px; }\n.lingting-root[data-global-status] .recording-controls.compact { min-height: 76px; padding: 12px 0; }\n.lingting-root[data-global-status] .error-notice { margin: 8px 0 0; }\n.lingting-sidebar-entry { display: flex; align-items: center; gap: 10px; border: 0; background: transparent; color: var(--dsw-alias-text-primary, #605972); padding: 10px 12px; width: 100%; border-radius: 9px; cursor: pointer; font: inherit; font-size: 14px; }\n.lingting-sidebar-entry:hover, .lingting-sidebar-entry[data-active] { background: #6650d814; color: #6650d8; }\n.lingting-sidebar-entry:focus-visible { outline: 2px solid #6650d8; outline-offset: 2px; }\n@container (max-width: 900px) {\n .lingting-root[data-embedded] .overview-note { display: none; }\n .lingting-root[data-embedded] .overview { grid-template-columns: 1fr 1fr; }\n .lingting-root[data-embedded] .list-heading { flex-wrap: wrap; }\n .lingting-root[data-embedded] .source-label { display: none; }\n}\n\n/* Standard DSH has no layout.business extension; keep the page in its public overlay slot. */\n.lt-business-surface { position: fixed; inset: 48px 12px 12px; z-index: 40; min-width: 0; overflow: hidden; border: 1px solid #e7e0fa; border-radius: 12px; background: #fff; box-shadow: 0 8px 32px #2c245221; pointer-events: auto; -webkit-app-region: no-drag; }\n";
5478
+ tag3.textContent = ".lingting-root { color-scheme: light; }\n/* Host \u9002\u914D\u5C42\u72B6\u6001\u63D0\u793A\uFF08\u6388\u6743/\u8EAB\u4EFD/\u76EE\u7684\u5730\u672A\u5C31\u7EEA\uFF09\uFF1A\u56FA\u5B9A\u9876\u90E8\uFF0C\u53EF\u5173\u95ED\uFF0C\u4E0D\u53C2\u4E0E\u9875\u9762\u5E03\u5C40 */\n.lt-host-notice { position: fixed; top: 12px; left: 50%; transform: translateX(-50%); z-index: 60; display: flex; align-items: center; gap: 12px; max-width: min(680px, calc(100vw - 32px)); padding: 10px 14px; border: 1px solid #e7e0fa; border-radius: 10px; background: #fff; box-shadow: 0 6px 24px rgb(40 28 74 / 16%); color: #605972; font-size: 13px; line-height: 1.5; }\n.lt-host-notice-text { flex: 1; }\n.lt-host-notice-close { flex-shrink: 0; border: 0; background: transparent; color: inherit; font-size: 16px; line-height: 1; padding: 2px 4px; border-radius: 6px; cursor: pointer; }\n.lt-host-notice-close:hover { background: #6650d814; }\n.lt-host-notice-close:focus-visible { outline: 2px solid #6650d8; outline-offset: 2px; }\n/* \u5D4C\u5165\u6A21\u5F0F\u4E0B\u6839\u5143\u7D20\u5373 .app\uFF08lingting-root app \u540C\u5143\u7D20\uFF09\uFF0C\u89C4\u5219\u9700\u7528\u7EC4\u5408\u9009\u62E9\u5668\uFF1B\u4FDD\u7559\u540E\u4EE3\u5F62\u5F0F\u517C\u5BB9\u53CC\u5C42\u5305\u88F9\u7ED3\u6784 */\n.lingting-root[data-embedded] { height: 100%; min-height: 0; container-type: inline-size; }\n.lingting-root[data-embedded].app, .lingting-root[data-embedded] .app { height: 100%; min-height: 0; display: flex; flex-direction: column; overflow: hidden; position: relative; padding-bottom: 0; }\n.lingting-root[data-embedded].app .app-header, .lingting-root[data-embedded] .app-header { height: 66px; flex-shrink: 0; }\n.lingting-root[data-embedded].app .header-inner, .lingting-root[data-embedded] .header-inner { padding: 0 28px; max-width: none; }\n.lingting-root[data-embedded].app .brand-caption, .lingting-root[data-embedded] .brand-caption { display: none; }\n.lingting-root[data-embedded].app .main-content, .lingting-root[data-embedded] .main-content { width: 100%; max-width: none; min-height: 0; flex: 1; overflow: auto; padding: 30px 28px 0; scrollbar-width: thin; }\n\n.lingting-root[data-embedded].app .toast, .lingting-root[data-embedded] .toast { position: absolute; top: 77px; }\n.lingting-root[data-global-status] { flex-shrink: 0; border-top: 1px solid #e7e0fa; background: white; padding: 0 24px; }\n.lingting-root[data-global-status] .recording-controls.compact { min-height: 76px; padding: 12px 0; }\n.lingting-root[data-global-status] .error-notice { margin: 8px 0 0; }\n.lingting-sidebar-entry { display: flex; align-items: center; gap: 10px; border: 0; background: transparent; color: var(--dsw-alias-text-primary, #605972); padding: 10px 12px; width: 100%; border-radius: 9px; cursor: pointer; font: inherit; font-size: 14px; }\n.lingting-sidebar-entry:hover, .lingting-sidebar-entry[data-active] { background: #6650d814; color: #6650d8; }\n.lingting-sidebar-entry:focus-visible { outline: 2px solid #6650d8; outline-offset: 2px; }\n@container (max-width: 900px) {\n .lingting-root[data-embedded] .overview-note { display: none; }\n .lingting-root[data-embedded] .overview { grid-template-columns: 1fr 1fr; }\n .lingting-root[data-embedded] .list-heading { flex-wrap: wrap; }\n .lingting-root[data-embedded] .source-label { display: none; }\n}\n\n/* Use the real center column, preserving the host sidebar and conversation state. */\n.lt-business-surface { position: absolute; inset: 0; z-index: 1; min-width: 0; overflow: hidden; background: #f8f9fc; pointer-events: auto; -webkit-app-region: no-drag; }\n/* Host reset styles must not remove the native dialog's centered placement. */\n.lingting-root .modal { margin: auto; background: #fff; }\n";
5427
5479
  document.querySelectorAll("style[data-plugin-css=" + JSON.stringify("dsh-xrxs-lingting/embedded.css") + "]").forEach((old) => old.remove());
5428
5480
  document.head.appendChild(tag3);
5429
5481
 
@@ -5431,7 +5483,7 @@ document.head.appendChild(tag3);
5431
5483
  var import_jsx_runtime21 = require("react/jsx-runtime");
5432
5484
  var ID = "dsh-xrxs-lingting";
5433
5485
  var inject = ["slots", "layout"];
5434
- var PanelBoundary = class extends import_react22.Component {
5486
+ var PanelBoundary = class extends import_react23.Component {
5435
5487
  state = { failed: false };
5436
5488
  static getDerivedStateFromError() {
5437
5489
  return { failed: true };
@@ -5472,8 +5524,8 @@ async function apply(ctx) {
5472
5524
  }));
5473
5525
  const unregisterPage = business.register(ID);
5474
5526
  function Entry({ wide }) {
5475
- const panel = (0, import_react22.useSyncExternalStore)(controller.subscribe, controller.getSnapshot);
5476
- const layout = (0, import_react22.useSyncExternalStore)(business.subscribe, business.getSnapshot);
5527
+ const panel = (0, import_react23.useSyncExternalStore)(controller.subscribe, controller.getSnapshot);
5528
+ const layout = (0, import_react23.useSyncExternalStore)(business.subscribe, business.getSnapshot);
5477
5529
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { type: "button", className: "lingting-sidebar-entry", "data-active": layout.activeId === ID || panel.open || void 0, title: "\u7075\u542C", "aria-label": "\u7075\u542C", onClick: () => business.open(ID), children: [
5478
5530
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Headphones, { size: 19 }),
5479
5531
  wide && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "\u7075\u542C" })
@@ -5483,9 +5535,9 @@ async function apply(ctx) {
5483
5535
  return activeId === ID ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PanelBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LingtingApp, { service, navigation, visible: true, embedded: true, hostState, onBackToHost: () => business.close(), onOpenLive: () => controller.open(), onOpenRecord: (id) => controller.openRecord(id) }) }) : null;
5484
5536
  }
5485
5537
  function Overlay() {
5486
- const page = (0, import_react22.useSyncExternalStore)(business.subscribe, business.getSnapshot, business.getSnapshot);
5538
+ const page = (0, import_react23.useSyncExternalStore)(business.subscribe, business.getSnapshot, business.getSnapshot);
5487
5539
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
5488
- !hostBusiness && page.activeId === ID && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("section", { className: "lt-business-surface", "aria-label": "\u7075\u542C", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Page, { activeId: page.activeId }) }),
5540
+ !hostBusiness && page.activeId === ID && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(BusinessSurface, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Page, { activeId: page.activeId }) }),
5489
5541
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PanelBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(XinHostNotice, { store: hostState }) }),
5490
5542
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PanelBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LingtingSidebar, { service, controller, onOpenPage: () => business.open(ID) }) }),
5491
5543
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PanelBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MeetingPrompt, { service }) })