dsh-mobile 0.1.0-alpha.20 → 0.1.0-alpha.22

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.en.md CHANGED
@@ -44,14 +44,6 @@ pnpm dsh --profile web
44
44
 
45
45
  Open **Mobile Access** in the lower-left DeepSeek Harness sidebar, enable it, and select **Create and copy key**. In the Android app, tap **Scan**, select the computer, and enter the key. The paired device remains trusted until it is revoked, expires, or its app data is cleared.
46
46
 
47
- ## Compatibility
48
-
49
- | DSH Mobile | Verified DeepSeek Harness releases |
50
- | --- | --- |
51
- | `0.1.0-alpha.20` | `0.1.0-rc.5`, `0.1.0-rc.6` |
52
-
53
- At startup, the plugin verifies the DSH Host version and the frontend dependencies required by the mobile layout. An unverified release fails with a clear error instead of serving a broken page. CI also tracks the DSH main branch layout slots and mobile semantic markers. If a DSH upgrade reports an incompatibility, update DSH Mobile first.
54
-
55
47
  ## Connection options
56
48
 
57
49
  | Client | Best for | Notes |
@@ -94,6 +86,14 @@ flowchart LR
94
86
 
95
87
  The Host face owns discovery, pairing, HTTPS, and the proxy. The Client face replaces only the phone layout entry while reusing native feature plugins. Neither the DeepSeek Harness source nor its desktop page on port 3080 is modified.
96
88
 
89
+ ## Compatibility
90
+
91
+ | DSH Mobile | Verified DeepSeek Harness releases |
92
+ | --- | --- |
93
+ | `0.1.0-alpha.22` | `0.1.0-rc.5`, `0.1.0-rc.6` |
94
+
95
+ At startup, the plugin verifies the DSH Host version and the frontend dependencies required by the mobile layout. An unverified release fails with a clear error instead of serving a broken page. CI also tracks the DSH main branch layout slots and mobile semantic markers. If a DSH upgrade reports an incompatibility, update DSH Mobile first.
96
+
97
97
  ## Security
98
98
 
99
99
  Use the plugin only on a trusted LAN or trusted VPN. Never expose it directly to the public Internet. A paired device is a fully trusted DeepSeek Harness operator. Revoke lost devices from the computer. See [SECURITY.md](SECURITY.md).
package/README.md CHANGED
@@ -65,14 +65,6 @@ pnpm dsh --profile web
65
65
 
66
66
  插件不会修改 DeepSeek Harness 源码。设置、证书、设备和自定义文件保存在 `$DSH_HOME/mobile-access/`。
67
67
 
68
- ## 兼容性
69
-
70
- | DSH Mobile | 已验证的 DeepSeek Harness |
71
- | --- | --- |
72
- | `0.1.0-alpha.20` | `0.1.0-rc.5`、`0.1.0-rc.6` |
73
-
74
- 插件会在启动时检查 DSH Host 版本和移动布局所需的前端依赖;遇到未经验证的版本会直接给出错误,不会带着不兼容页面继续启动。CI 也会持续检查 DSH 主分支的布局插槽和移动端语义标记。升级 DSH 后如遇兼容提示,请先升级 DSH Mobile。
75
-
76
68
  ## 连接方式
77
69
 
78
70
 
@@ -133,6 +125,14 @@ flowchart LR
133
125
 
134
126
  插件包含两部分:Host face 提供发现、配对、HTTPS 和回环代理;Client face 替换移动端的布局入口,并复用原生功能插件。DeepSeek Harness 的源码和 3080 桌面页面都不会被修改,安装和卸载仍完全通过插件机制完成。
135
127
 
128
+ ## 兼容性
129
+
130
+ | DSH Mobile | 已验证的 DeepSeek Harness |
131
+ | --- | --- |
132
+ | `0.1.0-alpha.22` | `0.1.0-rc.5`、`0.1.0-rc.6` |
133
+
134
+ 插件会在启动时检查 DSH Host 版本和移动布局所需的前端依赖;遇到未经验证的版本会直接给出错误,不会带着不兼容页面继续启动。CI 也会持续检查 DSH 主分支的布局插槽和移动端语义标记。升级 DSH 后如遇兼容提示,请先升级 DSH Mobile。
135
+
136
136
  ## 安全
137
137
 
138
138
  - 仅在可信家庭、办公局域网或可信 VPN 中使用,不要转发到公网。
package/lib/client.js CHANGED
@@ -90,28 +90,10 @@ window.__ModuleLoader__.load({
90
90
  [data-dsh-mobile-center] [class*="_card"]:has(textarea) button[aria-label^="选择模型"] [class*="_triggerLabel"] { max-width:78px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
91
91
  [data-dsh-mobile-center] [class*="_root"]:has(> [class*="_card"] textarea) { box-sizing:border-box !important; width:100% !important; padding:0 0 8px !important; }
92
92
  [data-dsh-mobile-center] [class*="_root"]:has(> [class*="_card"] textarea) > [class=""]:last-child { display:none !important; }
93
- .dsh-native-mobile-attach { display:inline-flex; align-items:center; justify-content:center; flex:0 0 44px; width:44px; height:44px; padding:0; border:0; border-radius:12px; background:transparent; color:var(--dsw-text-secondary,#5e6673); cursor:pointer; }
94
- .dsh-native-mobile-attach:active { background:var(--dsw-bg-subtle,#f1f3f6); }
95
- .dsh-native-mobile-attach:focus-visible { outline:2px solid var(--dsw-accent,#4c7eea); outline-offset:2px; }
96
- .dsh-native-mobile-attach:disabled { cursor:not-allowed; opacity:.38; }
97
- .dsh-native-mobile-attach svg { width:22px; height:22px; }
98
- .dsh-native-mobile-sheet-mask { position:fixed; z-index:1080; inset:0; border:0; background:rgb(15 23 42 / 32%); }
99
- .dsh-native-mobile-sheet-mask[hidden] { display:none; }
100
- .dsh-native-mobile-sheet { position:fixed; z-index:1081; right:0; bottom:0; left:0; display:flex; flex-direction:column; gap:8px; max-height:min(78dvh,680px); padding:8px 16px max(18px,env(safe-area-inset-bottom)); overflow-y:auto; border-radius:22px 22px 0 0; background:var(--dsw-alias-bg-layer-2,#fff); box-shadow:0 -16px 44px rgb(15 23 42 / 16%); animation:dsh-mobile-sheet-in 220ms var(--dsh-mobile-motion-ease); }
101
- .dsh-native-mobile-sheet[hidden] { display:none; }
102
- .dsh-native-mobile-sheet__header { position:sticky; z-index:1; top:-8px; display:flex; align-items:center; justify-content:space-between; min-height:48px; padding:8px 0; background:var(--dsw-alias-bg-layer-2,#fff); }
103
- .dsh-native-mobile-sheet__header strong { font-size:17px; font-weight:600; }
104
- .dsh-native-mobile-sheet__close { width:44px; height:44px; border:0; border-radius:12px; background:transparent; color:inherit; font-size:24px; }
105
- .dsh-native-mobile-sheet__path { margin:0 0 4px; overflow-wrap:anywhere; color:var(--dsw-alias-label-secondary,#6b7280); font-size:12px; }
106
- .dsh-native-mobile-sheet__choice { display:flex; flex-direction:column; align-items:flex-start; gap:2px; width:100%; min-height:56px; padding:10px 14px; border:1px solid var(--dsw-alias-border-subtle,#e2e6eb); border-radius:14px; background:var(--dsw-alias-bg-layer-2,#fff); color:inherit; text-align:left; }
107
- .dsh-native-mobile-sheet__choice:active { background:var(--dsw-alias-interactive-bg-hover,#f1f3f6); }
108
- .dsh-native-mobile-sheet__choice small { color:var(--dsw-alias-label-secondary,#6b7280); }
109
- .dsh-native-mobile-sheet__error { margin:4px 0; color:var(--dsw-alias-status-error,#b42318); font-size:13px; }
110
93
  }
111
94
  @keyframes dsh-mobile-fade-in { from { opacity:0; } }
112
95
  @keyframes dsh-mobile-panel-in { from { opacity:.72; transform:translateY(6px); } }
113
96
  @keyframes dsh-mobile-view-in { from { opacity:.58; transform:translateY(5px); } }
114
- @keyframes dsh-mobile-sheet-in { from { opacity:.7; transform:translateY(18px); } }
115
97
  @media (max-width:420px) {
116
98
  [data-dsh-mobile-header] [class*="_headerActions"] { max-width:42vw; }
117
99
  [data-dsh-mobile-header] [class*="_titleRow"] { min-height:50px; }
@@ -122,8 +104,7 @@ window.__ModuleLoader__.load({
122
104
  [data-dsh-mobile-sidebar-root],[data-dsh-mobile-details] { transition:none !important; }
123
105
  .dsh-native-mobile-backdrop:not([hidden]),[data-dsh-mobile-settings],
124
106
  [data-dsh-mobile-settings-content][data-dsh-mobile-view-transition="true"],
125
- [data-dsh-mobile-view][data-dsh-mobile-view-transition="true"],
126
- .dsh-native-mobile-sheet { animation:none !important; }
107
+ [data-dsh-mobile-view][data-dsh-mobile-view-transition="true"] { animation:none !important; }
127
108
  }
128
109
  `;
129
110
  function classToken(element, suffix) {
@@ -132,27 +113,7 @@ window.__ModuleLoader__.load({
132
113
  function firstByClassSuffix(root, suffix) {
133
114
  return Array.from(root.querySelectorAll("[class]")).find((element) => classToken(element, suffix));
134
115
  }
135
- function composerCard(textarea) {
136
- let candidate = textarea.parentElement;
137
- while (candidate !== null && !classToken(candidate, "_card")) candidate = candidate.parentElement;
138
- return candidate ?? void 0;
139
- }
140
- function paperclipIcon() {
141
- const namespace = "http://www.w3.org/2000/svg";
142
- const svg = document.createElementNS(namespace, "svg");
143
- svg.setAttribute("viewBox", "0 0 24 24");
144
- svg.setAttribute("fill", "none");
145
- svg.setAttribute("stroke", "currentColor");
146
- svg.setAttribute("stroke-width", "2");
147
- svg.setAttribute("stroke-linecap", "round");
148
- svg.setAttribute("stroke-linejoin", "round");
149
- svg.setAttribute("aria-hidden", "true");
150
- const path = document.createElementNS(namespace, "path");
151
- path.setAttribute("d", "m21.4 11.6-8.9 8.9a6 6 0 0 1-8.5-8.5l9.6-9.6a4 4 0 0 1 5.7 5.7l-9.7 9.6a2 2 0 0 1-2.8-2.8l8.9-8.9");
152
- svg.append(path);
153
- return svg;
154
- }
155
- /** Add mobile semantics and phone-local file actions without replacing feature trees. */
116
+ /** Add mobile semantics without replacing feature trees. */
156
117
  function installNativeMobileSurface() {
157
118
  document.documentElement.classList.add("dsh-native-mobile-active");
158
119
  const setInputMode = (mode) => {
@@ -182,149 +143,6 @@ window.__ModuleLoader__.load({
182
143
  let transitionRestartFrame = 0;
183
144
  let transitionTimer = 0;
184
145
  let transitionTarget;
185
- const fileInput = document.createElement("input");
186
- fileInput.type = "file";
187
- fileInput.accept = "image/*";
188
- fileInput.multiple = true;
189
- fileInput.hidden = true;
190
- fileInput.setAttribute("aria-hidden", "true");
191
- const attach = document.createElement("button");
192
- attach.type = "button";
193
- attach.className = "dsh-native-mobile-attach";
194
- attach.setAttribute("aria-label", "添加图片");
195
- attach.setAttribute("title", "添加图片");
196
- attach.append(paperclipIcon());
197
- document.body.append(fileInput);
198
- const sheetMask = document.createElement("button");
199
- sheetMask.type = "button";
200
- sheetMask.className = "dsh-native-mobile-sheet-mask";
201
- sheetMask.hidden = true;
202
- sheetMask.setAttribute("aria-label", "关闭图片选择");
203
- const sheet = document.createElement("section");
204
- sheet.className = "dsh-native-mobile-sheet";
205
- sheet.hidden = true;
206
- sheet.setAttribute("aria-label", "添加图片");
207
- document.body.append(sheetMask, sheet);
208
- const handFilesToComposer = (files) => {
209
- const textarea = document.querySelector("[data-dsh-mobile-center] textarea");
210
- if (textarea === null || files.length === 0) return;
211
- const paste = new Event("paste", {
212
- bubbles: true,
213
- cancelable: true
214
- });
215
- Object.defineProperty(paste, "clipboardData", { value: Object.freeze({
216
- files,
217
- items: Object.freeze(files.map((file) => Object.freeze({
218
- kind: "file",
219
- type: file.type,
220
- getAsFile: () => file
221
- }))),
222
- getData: () => ""
223
- }) });
224
- textarea.dispatchEvent(paste);
225
- };
226
- const closeSheet = () => {
227
- sheet.hidden = true;
228
- sheetMask.hidden = true;
229
- sheet.replaceChildren();
230
- };
231
- const sheetHeader = (title) => {
232
- const header = document.createElement("header");
233
- header.className = "dsh-native-mobile-sheet__header";
234
- const heading = document.createElement("strong");
235
- heading.textContent = title;
236
- const close = document.createElement("button");
237
- close.type = "button";
238
- close.className = "dsh-native-mobile-sheet__close";
239
- close.setAttribute("aria-label", "关闭");
240
- close.textContent = "×";
241
- close.addEventListener("click", closeSheet);
242
- header.append(heading, close);
243
- sheet.append(header);
244
- };
245
- const choice = (title, detail, action) => {
246
- const button = document.createElement("button");
247
- button.type = "button";
248
- button.className = "dsh-native-mobile-sheet__choice";
249
- const label = document.createElement("span");
250
- label.textContent = title;
251
- const hint = document.createElement("small");
252
- hint.textContent = detail;
253
- button.append(label, hint);
254
- button.addEventListener("click", action);
255
- return button;
256
- };
257
- const showSheet = () => {
258
- sheet.hidden = false;
259
- sheetMask.hidden = false;
260
- };
261
- const openComputerImages = async (path) => {
262
- sheet.replaceChildren();
263
- sheetHeader("电脑图片");
264
- const progress = document.createElement("p");
265
- progress.className = "dsh-native-mobile-sheet__path";
266
- progress.textContent = "正在读取电脑目录…";
267
- sheet.append(progress);
268
- showSheet();
269
- try {
270
- const suffix = path === void 0 ? "" : `?path=${encodeURIComponent(path)}`;
271
- const response = await fetch(`/mobile-access/computer-images${suffix}`, {
272
- credentials: "same-origin",
273
- cache: "no-store"
274
- });
275
- if (!response.ok) throw new Error(`读取失败(${String(response.status)})`);
276
- const listing = await response.json();
277
- progress.textContent = listing.path;
278
- if (listing.parent !== void 0) sheet.append(choice("返回上一级", listing.parent, () => {
279
- openComputerImages(listing.parent);
280
- }));
281
- for (const entry of listing.entries) {
282
- if (entry.kind === "directory") {
283
- sheet.append(choice(entry.name, "文件夹", () => {
284
- openComputerImages(entry.path);
285
- }));
286
- continue;
287
- }
288
- const row = choice(entry.name, "添加这张电脑图片", () => {
289
- row.disabled = true;
290
- fetch(`/mobile-access/computer-image?path=${encodeURIComponent(entry.path)}`, {
291
- credentials: "same-origin",
292
- cache: "no-store"
293
- }).then(async (response) => {
294
- if (!response.ok) throw new Error(`读取失败(${String(response.status)})`);
295
- const blob = await response.blob();
296
- handFilesToComposer([new File([blob], entry.name, { type: blob.type })]);
297
- closeSheet();
298
- }).catch((error) => {
299
- row.disabled = false;
300
- progress.className = "dsh-native-mobile-sheet__error";
301
- progress.textContent = error instanceof Error ? error.message : String(error);
302
- });
303
- });
304
- sheet.append(row);
305
- }
306
- } catch (error) {
307
- progress.className = "dsh-native-mobile-sheet__error";
308
- progress.textContent = error instanceof Error ? error.message : String(error);
309
- }
310
- };
311
- const openAttachmentSources = () => {
312
- sheet.replaceChildren();
313
- sheetHeader("添加图片");
314
- sheet.append(choice("从手机选择", "相册、相机或手机存储", () => {
315
- closeSheet();
316
- fileInput.click();
317
- }), choice("从电脑选择", "在手机页面浏览电脑中的图片", () => {
318
- openComputerImages();
319
- }));
320
- showSheet();
321
- };
322
- attach.addEventListener("click", openAttachmentSources);
323
- sheetMask.addEventListener("click", closeSheet);
324
- fileInput.addEventListener("change", () => {
325
- handFilesToComposer([...fileInput.files ?? []]);
326
- fileInput.value = "";
327
- });
328
146
  const animateNavigation = (event) => {
329
147
  if (!(event.target instanceof Element)) return;
330
148
  const trigger = event.target.closest("button,a,[role=\"tab\"],[aria-selected]");
@@ -403,11 +221,6 @@ window.__ModuleLoader__.load({
403
221
  firstByClassSuffix(content, "_options")?.setAttribute("data-dsh-mobile-settings-options", "true");
404
222
  }
405
223
  }
406
- const textarea = center?.querySelector("textarea");
407
- const card = textarea === null || textarea === void 0 ? void 0 : composerCard(textarea);
408
- const tools = card === void 0 ? void 0 : firstByClassSuffix(card, "_tools");
409
- attach.disabled = textarea === void 0 || textarea === null || textarea.disabled || textarea.readOnly;
410
- if (tools !== void 0 && attach.parentElement !== tools) tools.append(attach);
411
224
  if (sidebar === void 0) return;
412
225
  sidebar.dataset.dshMobileSidebar = "true";
413
226
  toggle = firstByClassSuffix(sidebar, "_toggle");
@@ -446,10 +259,6 @@ window.__ModuleLoader__.load({
446
259
  document.removeEventListener("keydown", onKeyDown, true);
447
260
  document.removeEventListener("click", animateNavigation);
448
261
  backdrop.remove();
449
- attach.remove();
450
- fileInput.remove();
451
- sheet.remove();
452
- sheetMask.remove();
453
262
  document.documentElement.classList.remove("dsh-native-mobile-active");
454
263
  delete document.documentElement.dataset.dshMobileInput;
455
264
  };
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["createElement"],"sources":["../src/native-mobile.ts","../src/client.ts"],"sourcesContent":["/** Mobile feature and compatibility rules applied to DSH React surfaces. */\nexport const NATIVE_MOBILE_STYLES = `\n@media (max-width:720px) {\n html.dsh-native-mobile-active,html.dsh-native-mobile-active body { width:100%; height:100%; overflow:hidden; }\n html.dsh-native-mobile-active { --dsh-mobile-motion-duration:200ms; --dsh-mobile-motion-ease:cubic-bezier(.22,1,.36,1); }\n html.dsh-native-mobile-active :is(a,button,[role=\"button\"],[role=\"tab\"],[tabindex]) { -webkit-tap-highlight-color:transparent; }\n html.dsh-native-mobile-active[data-dsh-mobile-input=\"touch\"] :is(a,button,[role=\"button\"],[role=\"tab\"],[tabindex]):focus { outline:none !important; }\n [data-dsh-mobile-frame] { grid-template-columns:0 minmax(0,1fr) 0 !important; width:100% !important; height:100dvh !important; overflow:hidden !important; }\n [data-dsh-mobile-center] { grid-column:2 !important; width:100vw !important; min-width:0 !important; }\n [data-dsh-mobile-center] > * { min-width:0 !important; }\n [data-dsh-mobile-header] { min-width:0; padding-right:12px !important; padding-left:50px !important; }\n [data-dsh-mobile-header] [class*=\"_titleRow\"] { box-sizing:border-box !important; min-width:0; min-height:52px !important; height:52px !important; gap:6px !important; padding:4px 8px !important; }\n [data-dsh-mobile-header] [class*=\"_titleCluster\"] { min-width:0; }\n [data-dsh-mobile-header] [class*=\"_crumbs\"] { min-width:0; overflow:hidden; }\n [data-dsh-mobile-header] [class*=\"_crumb\"] { max-width:46vw; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n [data-dsh-mobile-header] [class*=\"_headerActions\"] { min-width:0; overflow-x:auto; scrollbar-width:none; }\n [data-dsh-mobile-header] [class*=\"_headerActions\"]::-webkit-scrollbar { display:none; }\n [data-dsh-mobile-header] [class*=\"_headerUtilities\"] { gap:2px !important; }\n [data-dsh-mobile-header] [class*=\"_sessionLogButton\"] { width:40px; min-width:40px; padding:0 !important; overflow:hidden; color:transparent; font-size:0 !important; }\n [data-dsh-mobile-header] [class*=\"_sessionLogButton\"] > * { display:none !important; }\n [data-dsh-mobile-header] [class*=\"_sessionLogButton\"]::after { color:var(--dsw-text, #171a21); content:\"日志\"; font-size:11px; font-weight:600; }\n [data-dsh-mobile-header] [class*=\"_tabs\"] { min-height:42px; overflow-x:auto; scrollbar-width:none; }\n [data-dsh-mobile-header] [class*=\"_tabs\"]::-webkit-scrollbar { display:none; }\n [data-dsh-mobile-sidebar] { position:fixed !important; z-index:240 !important; inset:0 auto 0 0 !important; width:0 !important; overflow:visible !important; }\n [data-dsh-mobile-sidebar-root] { position:fixed !important; z-index:241 !important; inset:0 auto 0 0 !important; height:100dvh !important; transition:transform var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease) !important; }\n [data-dsh-mobile-sidebar][data-open=\"true\"] [data-dsh-mobile-sidebar-root] { width:min(88vw,340px) !important; box-shadow:18px 0 46px rgb(15 23 42 / 18%); }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] { width:0 !important; border:0 !important; background:transparent !important; box-shadow:none !important; overflow:visible !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] > :not(:has([data-dsh-mobile-toggle])) { display:none !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] > :has([data-dsh-mobile-toggle]) { position:fixed !important; z-index:244 !important; top:env(safe-area-inset-top) !important; left:0 !important; width:50px !important; height:52px !important; padding:4px !important; border:0 !important; background:transparent !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] > :has([data-dsh-mobile-toggle]) > :not([data-dsh-mobile-toggle]) { display:none !important; }\n [data-dsh-mobile-toggle] { width:44px !important; height:44px !important; min-width:44px !important; min-height:44px !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-toggle] svg { display:none !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-toggle]::after { width:20px; height:2px; border-radius:2px; background:currentColor; box-shadow:0 -6px 0 currentColor,0 6px 0 currentColor; content:\"\"; }\n .dsh-native-mobile-backdrop { position:fixed; z-index:235; inset:0; border:0; background:rgb(15 23 42 / 32%); }\n .dsh-native-mobile-backdrop:not([hidden]) { animation:dsh-mobile-fade-in var(--dsh-mobile-motion-duration) ease-out; }\n .dsh-native-mobile-backdrop[hidden] { display:none; }\n [data-dsh-mobile-details] { position:fixed !important; z-index:250 !important; inset:0 0 0 auto !important; width:min(94vw,460px) !important; max-width:none !important; transform:translateX(100%); transition:transform var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease); background:var(--dsw-bg, #fff); box-shadow:-18px 0 46px rgb(15 23 42 / 18%); }\n [data-dsh-mobile-details][data-open=\"true\"] { transform:translateX(0); }\n [data-dsh-mobile-handle] { display:none !important; }\n [data-dsh-mobile-settings] { flex-direction:column !important; width:100vw !important; height:100dvh !important; max-width:none !important; border-radius:0 !important; animation:dsh-mobile-panel-in var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease); }\n [data-dsh-mobile-settings-nav] { flex:none !important; width:100% !important; padding:max(14px,env(safe-area-inset-top)) 12px 8px !important; gap:10px !important; border-bottom:1px solid var(--dsw-alias-border-subtle,#e8ebef); }\n [data-dsh-mobile-settings-nav] [class*=\"_navTitle\"] { padding:0 8px !important; font-size:18px !important; line-height:28px !important; }\n [data-dsh-mobile-settings-list] { flex-direction:row !important; gap:4px !important; overflow-x:auto !important; scrollbar-width:none; }\n [data-dsh-mobile-settings-list]::-webkit-scrollbar { display:none; }\n [data-dsh-mobile-settings-list] [class*=\"_navCell\"] { flex:0 0 auto !important; min-width:max-content !important; height:44px !important; padding:10px 12px !important; }\n [data-dsh-mobile-settings-list] [aria-current=\"true\"] { border-color:transparent !important; outline:0 !important; box-shadow:none !important; }\n [data-dsh-mobile-settings-content] { flex:1 1 auto !important; width:100% !important; min-height:0 !important; }\n [data-dsh-mobile-settings-header] { height:48px !important; min-height:48px !important; padding:10px 12px 6px !important; }\n [data-dsh-mobile-settings-header] [class*=\"_close\"] { width:36px !important; height:36px !important; }\n [data-dsh-mobile-settings-options] { box-sizing:border-box !important; width:100% !important; padding:4px 16px max(24px,env(safe-area-inset-bottom)) !important; overflow-x:hidden !important; }\n [data-dsh-mobile-settings-options] > * { width:100% !important; min-width:0 !important; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] > [class*=\"_row\"] { flex-direction:column !important; align-items:stretch !important; gap:12px !important; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] [class*=\"_rowText\"] { width:100% !important; padding-right:0 !important; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] [class*=\"_selector\"] { box-sizing:border-box !important; align-self:flex-start !important; justify-content:space-between !important; min-width:0 !important; min-height:44px !important; max-width:100% !important; }\n [data-dsh-mobile-settings-options] :is(input,select,textarea,button) { max-width:100%; }\n [data-dsh-mobile-settings-options] :is(input,select,textarea) { box-sizing:border-box; width:100%; min-width:0; }\n [data-dsh-mobile-settings-options] [class*=\"_head\"] { min-width:0; flex-wrap:wrap; }\n [data-dsh-mobile-settings-content][data-dsh-mobile-view-transition=\"true\"],\n [data-dsh-mobile-view][data-dsh-mobile-view-transition=\"true\"] { animation:dsh-mobile-view-in var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease); }\n [data-dsh-mobile-center] textarea { font-size:16px !important; }\n [data-dsh-mobile-center] table { display:block; max-width:100%; overflow-x:auto; }\n [data-dsh-mobile-center] pre { max-width:100%; overflow-x:auto; }\n [data-dsh-mobile-center] :is(img,video,canvas,svg) { max-width:100%; }\n [data-dsh-mobile-message-scroll] { box-sizing:border-box !important; width:100% !important; padding:12px 16px 20px !important; }\n [data-dsh-mobile-message-column] { box-sizing:border-box !important; width:100% !important; max-width:none !important; margin:0 !important; padding:0 !important; gap:14px !important; }\n [data-dsh-mobile-message-column] > * { width:100% !important; max-width:100% !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] { box-sizing:border-box !important; display:grid !important; grid-template-columns:16px minmax(0,1fr) !important; grid-auto-rows:auto !important; align-items:center !important; column-gap:6px !important; width:100% !important; height:auto !important; min-height:44px !important; padding:5px 0 !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > [class*=\"_leading\"] { grid-column:1 !important; grid-row:1 !important; margin-right:0 !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > [class*=\"_title\"] { grid-column:2 !important; grid-row:1 !important; min-width:0 !important; overflow:hidden !important; text-overflow:ellipsis !important; white-space:nowrap !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > :is([class*=\"_sep\"],[class*=\"_separator\"]) { display:none !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > :is([class*=\"_summary\"],[class*=\"_fileLink\"]) { grid-column:2 !important; grid-row:2 !important; width:100% !important; min-width:0 !important; max-width:100% !important; overflow:hidden !important; line-height:20px !important; text-overflow:ellipsis !important; white-space:nowrap !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > [class*=\"_summarySuffix\"] { grid-column:2 !important; grid-row:3 !important; margin-left:0 !important; }\n [data-dsh-mobile-message-column] [data-context-fields] > * { display:grid !important; grid-template-columns:minmax(72px,30%) minmax(0,1fr) !important; gap:4px 10px !important; }\n [data-dsh-mobile-message-column] [class*=\"_ioSection\"] { grid-template-columns:1fr !important; row-gap:4px !important; }\n [data-dsh-mobile-message-column] [class*=\"_body\"] { max-width:100% !important; overflow-wrap:anywhere; }\n [data-dsh-mobile-center] [class*=\"_composer\"] { padding-left:8px !important; padding-right:8px !important; padding-bottom:max(8px,env(safe-area-inset-bottom)) !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_row\"] { display:flex !important; align-items:center !important; gap:4px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_tools\"] { flex:0 0 auto !important; width:auto !important; min-width:0 !important; gap:6px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_trailing\"] { flex:1 1 auto !important; min-width:0 !important; gap:6px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_trailing\"] [class*=\"_root\"]:has(button[aria-label^=\"选择模型\"]) { flex:1 1 auto !important; min-width:0 !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) button[aria-label^=\"选择模型\"] { width:100% !important; min-width:0 !important; padding-left:6px !important; padding-right:4px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) button[aria-label^=\"选择模型\"] [class*=\"_triggerLabel\"] { max-width:78px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n [data-dsh-mobile-center] [class*=\"_root\"]:has(> [class*=\"_card\"] textarea) { box-sizing:border-box !important; width:100% !important; padding:0 0 8px !important; }\n [data-dsh-mobile-center] [class*=\"_root\"]:has(> [class*=\"_card\"] textarea) > [class=\"\"]:last-child { display:none !important; }\n .dsh-native-mobile-attach { display:inline-flex; align-items:center; justify-content:center; flex:0 0 44px; width:44px; height:44px; padding:0; border:0; border-radius:12px; background:transparent; color:var(--dsw-text-secondary,#5e6673); cursor:pointer; }\n .dsh-native-mobile-attach:active { background:var(--dsw-bg-subtle,#f1f3f6); }\n .dsh-native-mobile-attach:focus-visible { outline:2px solid var(--dsw-accent,#4c7eea); outline-offset:2px; }\n .dsh-native-mobile-attach:disabled { cursor:not-allowed; opacity:.38; }\n .dsh-native-mobile-attach svg { width:22px; height:22px; }\n .dsh-native-mobile-sheet-mask { position:fixed; z-index:1080; inset:0; border:0; background:rgb(15 23 42 / 32%); }\n .dsh-native-mobile-sheet-mask[hidden] { display:none; }\n .dsh-native-mobile-sheet { position:fixed; z-index:1081; right:0; bottom:0; left:0; display:flex; flex-direction:column; gap:8px; max-height:min(78dvh,680px); padding:8px 16px max(18px,env(safe-area-inset-bottom)); overflow-y:auto; border-radius:22px 22px 0 0; background:var(--dsw-alias-bg-layer-2,#fff); box-shadow:0 -16px 44px rgb(15 23 42 / 16%); animation:dsh-mobile-sheet-in 220ms var(--dsh-mobile-motion-ease); }\n .dsh-native-mobile-sheet[hidden] { display:none; }\n .dsh-native-mobile-sheet__header { position:sticky; z-index:1; top:-8px; display:flex; align-items:center; justify-content:space-between; min-height:48px; padding:8px 0; background:var(--dsw-alias-bg-layer-2,#fff); }\n .dsh-native-mobile-sheet__header strong { font-size:17px; font-weight:600; }\n .dsh-native-mobile-sheet__close { width:44px; height:44px; border:0; border-radius:12px; background:transparent; color:inherit; font-size:24px; }\n .dsh-native-mobile-sheet__path { margin:0 0 4px; overflow-wrap:anywhere; color:var(--dsw-alias-label-secondary,#6b7280); font-size:12px; }\n .dsh-native-mobile-sheet__choice { display:flex; flex-direction:column; align-items:flex-start; gap:2px; width:100%; min-height:56px; padding:10px 14px; border:1px solid var(--dsw-alias-border-subtle,#e2e6eb); border-radius:14px; background:var(--dsw-alias-bg-layer-2,#fff); color:inherit; text-align:left; }\n .dsh-native-mobile-sheet__choice:active { background:var(--dsw-alias-interactive-bg-hover,#f1f3f6); }\n .dsh-native-mobile-sheet__choice small { color:var(--dsw-alias-label-secondary,#6b7280); }\n .dsh-native-mobile-sheet__error { margin:4px 0; color:var(--dsw-alias-status-error,#b42318); font-size:13px; }\n}\n@keyframes dsh-mobile-fade-in { from { opacity:0; } }\n@keyframes dsh-mobile-panel-in { from { opacity:.72; transform:translateY(6px); } }\n@keyframes dsh-mobile-view-in { from { opacity:.58; transform:translateY(5px); } }\n@keyframes dsh-mobile-sheet-in { from { opacity:.7; transform:translateY(18px); } }\n@media (max-width:420px) {\n [data-dsh-mobile-header] [class*=\"_headerActions\"] { max-width:42vw; }\n [data-dsh-mobile-header] [class*=\"_titleRow\"] { min-height:50px; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] [class*=\"_selector\"] { align-self:stretch !important; width:100% !important; }\n [data-dsh-mobile-message-column] [data-context-fields] > * { grid-template-columns:1fr !important; }\n}\n@media (prefers-reduced-motion:reduce) {\n [data-dsh-mobile-sidebar-root],[data-dsh-mobile-details] { transition:none !important; }\n .dsh-native-mobile-backdrop:not([hidden]),[data-dsh-mobile-settings],\n [data-dsh-mobile-settings-content][data-dsh-mobile-view-transition=\"true\"],\n [data-dsh-mobile-view][data-dsh-mobile-view-transition=\"true\"],\n .dsh-native-mobile-sheet { animation:none !important; }\n}\n`\n\nfunction classToken(element: Element, suffix: string): boolean {\n return Array.from(element.classList).some(value => value.endsWith(suffix))\n}\n\nfunction firstByClassSuffix(root: ParentNode, suffix: string): HTMLElement | undefined {\n return Array.from(root.querySelectorAll<HTMLElement>('[class]')).find(element => classToken(element, suffix))\n}\n\nfunction composerCard(textarea: HTMLTextAreaElement): HTMLElement | undefined {\n let candidate: HTMLElement | null = textarea.parentElement\n while (candidate !== null && !classToken(candidate, '_card')) candidate = candidate.parentElement\n return candidate ?? undefined\n}\n\nfunction paperclipIcon(): SVGSVGElement {\n const namespace = 'http://www.w3.org/2000/svg'\n const svg = document.createElementNS(namespace, 'svg')\n svg.setAttribute('viewBox', '0 0 24 24')\n svg.setAttribute('fill', 'none')\n svg.setAttribute('stroke', 'currentColor')\n svg.setAttribute('stroke-width', '2')\n svg.setAttribute('stroke-linecap', 'round')\n svg.setAttribute('stroke-linejoin', 'round')\n svg.setAttribute('aria-hidden', 'true')\n const path = document.createElementNS(namespace, 'path')\n path.setAttribute('d', 'm21.4 11.6-8.9 8.9a6 6 0 0 1-8.5-8.5l9.6-9.6a4 4 0 0 1 5.7 5.7l-9.7 9.6a2 2 0 0 1-2.8-2.8l8.9-8.9')\n svg.append(path)\n return svg\n}\n\n/** Add mobile semantics and phone-local file actions without replacing feature trees. */\nexport function installNativeMobileSurface(): () => void {\n document.documentElement.classList.add('dsh-native-mobile-active')\n const setInputMode = (mode: 'keyboard' | 'touch'): void => {\n document.documentElement.dataset.dshMobileInput = mode\n }\n const onPointerDown = (event: PointerEvent): void => {\n if (event.pointerType === 'touch' || event.pointerType === 'pen') setInputMode('touch')\n }\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key === 'Tab' || event.key.startsWith('Arrow')) setInputMode('keyboard')\n }\n document.addEventListener('pointerdown', onPointerDown, true)\n document.addEventListener('keydown', onKeyDown, true)\n const backdrop = document.createElement('button')\n backdrop.type = 'button'\n backdrop.className = 'dsh-native-mobile-backdrop'\n backdrop.hidden = true\n backdrop.setAttribute('aria-label', '关闭工作区导航')\n document.body.append(backdrop)\n let frame: HTMLElement | undefined\n let sidebar: HTMLElement | undefined\n let sidebarRoot: HTMLElement | undefined\n let toggle: HTMLButtonElement | undefined\n let viewArea: HTMLElement | undefined\n let scheduled = 0\n let transitionFrame = 0\n let transitionRestartFrame = 0\n let transitionTimer = 0\n let transitionTarget: HTMLElement | undefined\n const fileInput = document.createElement('input')\n fileInput.type = 'file'\n fileInput.accept = 'image/*'\n fileInput.multiple = true\n fileInput.hidden = true\n fileInput.setAttribute('aria-hidden', 'true')\n const attach = document.createElement('button')\n attach.type = 'button'\n attach.className = 'dsh-native-mobile-attach'\n attach.setAttribute('aria-label', '添加图片')\n attach.setAttribute('title', '添加图片')\n attach.append(paperclipIcon())\n document.body.append(fileInput)\n const sheetMask = document.createElement('button')\n sheetMask.type = 'button'\n sheetMask.className = 'dsh-native-mobile-sheet-mask'\n sheetMask.hidden = true\n sheetMask.setAttribute('aria-label', '关闭图片选择')\n const sheet = document.createElement('section')\n sheet.className = 'dsh-native-mobile-sheet'\n sheet.hidden = true\n sheet.setAttribute('aria-label', '添加图片')\n document.body.append(sheetMask, sheet)\n\n const handFilesToComposer = (files: readonly File[]): void => {\n const textarea = document.querySelector<HTMLTextAreaElement>('[data-dsh-mobile-center] textarea')\n if (textarea === null || files.length === 0) return\n const paste = new Event('paste', { bubbles: true, cancelable: true })\n Object.defineProperty(paste, 'clipboardData', {\n value: Object.freeze({\n files,\n items: Object.freeze(files.map(file => Object.freeze({\n kind: 'file',\n type: file.type,\n getAsFile: () => file,\n }))),\n getData: () => '',\n }),\n })\n textarea.dispatchEvent(paste)\n }\n\n const closeSheet = (): void => {\n sheet.hidden = true\n sheetMask.hidden = true\n sheet.replaceChildren()\n }\n const sheetHeader = (title: string): void => {\n const header = document.createElement('header')\n header.className = 'dsh-native-mobile-sheet__header'\n const heading = document.createElement('strong')\n heading.textContent = title\n const close = document.createElement('button')\n close.type = 'button'\n close.className = 'dsh-native-mobile-sheet__close'\n close.setAttribute('aria-label', '关闭')\n close.textContent = '×'\n close.addEventListener('click', closeSheet)\n header.append(heading, close)\n sheet.append(header)\n }\n const choice = (title: string, detail: string, action: () => void): HTMLButtonElement => {\n const button = document.createElement('button')\n button.type = 'button'\n button.className = 'dsh-native-mobile-sheet__choice'\n const label = document.createElement('span')\n label.textContent = title\n const hint = document.createElement('small')\n hint.textContent = detail\n button.append(label, hint)\n button.addEventListener('click', action)\n return button\n }\n const showSheet = (): void => {\n sheet.hidden = false\n sheetMask.hidden = false\n }\n const openComputerImages = async (path?: string): Promise<void> => {\n sheet.replaceChildren()\n sheetHeader('电脑图片')\n const progress = document.createElement('p')\n progress.className = 'dsh-native-mobile-sheet__path'\n progress.textContent = '正在读取电脑目录…'\n sheet.append(progress)\n showSheet()\n try {\n const suffix = path === undefined ? '' : `?path=${encodeURIComponent(path)}`\n const response = await fetch(`/mobile-access/computer-images${suffix}`, { credentials: 'same-origin', cache: 'no-store' })\n if (!response.ok) throw new Error(`读取失败(${String(response.status)})`)\n const listing = await response.json() as {\n readonly path: string\n readonly parent?: string\n readonly entries: readonly { readonly kind: 'directory' | 'image'; readonly name: string; readonly path: string }[]\n }\n progress.textContent = listing.path\n if (listing.parent !== undefined) sheet.append(choice('返回上一级', listing.parent, () => { void openComputerImages(listing.parent) }))\n for (const entry of listing.entries) {\n if (entry.kind === 'directory') {\n sheet.append(choice(entry.name, '文件夹', () => { void openComputerImages(entry.path) }))\n continue\n }\n const row = choice(entry.name, '添加这张电脑图片', () => {\n row.disabled = true\n void fetch(`/mobile-access/computer-image?path=${encodeURIComponent(entry.path)}`, { credentials: 'same-origin', cache: 'no-store' })\n .then(async response => {\n if (!response.ok) throw new Error(`读取失败(${String(response.status)})`)\n const blob = await response.blob()\n handFilesToComposer([new File([blob], entry.name, { type: blob.type })])\n closeSheet()\n })\n .catch(error => {\n row.disabled = false\n progress.className = 'dsh-native-mobile-sheet__error'\n progress.textContent = error instanceof Error ? error.message : String(error)\n })\n })\n sheet.append(row)\n }\n } catch (error) {\n progress.className = 'dsh-native-mobile-sheet__error'\n progress.textContent = error instanceof Error ? error.message : String(error)\n }\n }\n const openAttachmentSources = (): void => {\n sheet.replaceChildren()\n sheetHeader('添加图片')\n sheet.append(\n choice('从手机选择', '相册、相机或手机存储', () => { closeSheet(); fileInput.click() }),\n choice('从电脑选择', '在手机页面浏览电脑中的图片', () => { void openComputerImages() }),\n )\n showSheet()\n }\n attach.addEventListener('click', openAttachmentSources)\n sheetMask.addEventListener('click', closeSheet)\n fileInput.addEventListener('change', () => {\n handFilesToComposer([...(fileInput.files ?? [])])\n fileInput.value = ''\n })\n\n const animateNavigation = (event: MouseEvent): void => {\n if (!(event.target instanceof Element)) return\n const trigger = event.target.closest<HTMLElement>('button,a,[role=\"tab\"],[aria-selected]')\n if (trigger === null || trigger.hasAttribute('disabled') || trigger.getAttribute('aria-disabled') === 'true') return\n if (trigger.getAttribute('aria-selected') === 'true' || trigger.getAttribute('aria-current') === 'true') return\n const settingsNavigation = trigger.closest('[data-dsh-mobile-settings-list]') !== null\n const conversationNavigation = trigger.matches('[role=\"tab\"]')\n const sidebarNavigation = trigger.closest('[data-dsh-mobile-sidebar-root]') !== null\n && trigger.closest('[data-dsh-mobile-toggle]') === null\n if (!settingsNavigation && !conversationNavigation && !sidebarNavigation) return\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return\n if (transitionFrame !== 0) cancelAnimationFrame(transitionFrame)\n if (transitionRestartFrame !== 0) cancelAnimationFrame(transitionRestartFrame)\n transitionFrame = requestAnimationFrame(() => {\n transitionFrame = 0\n const target = settingsNavigation\n ? document.querySelector<HTMLElement>('[data-dsh-mobile-settings-content]')\n : viewArea\n if (target === null || target === undefined) return\n transitionTarget?.removeAttribute('data-dsh-mobile-view-transition')\n target.removeAttribute('data-dsh-mobile-view-transition')\n transitionRestartFrame = requestAnimationFrame(() => {\n transitionRestartFrame = 0\n transitionTarget = target\n target.dataset.dshMobileViewTransition = 'true'\n if (transitionTimer !== 0) clearTimeout(transitionTimer)\n transitionTimer = window.setTimeout(() => {\n target.removeAttribute('data-dsh-mobile-view-transition')\n if (transitionTarget === target) transitionTarget = undefined\n transitionTimer = 0\n }, 240)\n })\n })\n }\n document.addEventListener('click', animateNavigation)\n\n const sync = (): void => {\n scheduled = 0\n frame = firstByClassSuffix(document, '_frame')\n const dedicatedCenter = document.querySelector<HTMLElement>('.dshm-main') ?? undefined\n if (frame !== undefined) frame.dataset.dshMobileFrame = 'true'\n sidebar = frame === undefined ? undefined : firstByClassSuffix(frame, '_sidebarCol')\n const center = frame === undefined ? dedicatedCenter : firstByClassSuffix(frame, '_centerCol')\n const details = frame === undefined ? undefined : firstByClassSuffix(frame, '_detailsCol')\n const handle = frame === undefined ? undefined : firstByClassSuffix(frame, '_handle')\n if (center === undefined) return\n if (center !== undefined) {\n center.dataset.dshMobileCenter = 'true'\n center.querySelector<HTMLElement>('header')?.setAttribute('data-dsh-mobile-header', 'true')\n viewArea = firstByClassSuffix(center, '_viewArea')\n if (viewArea !== undefined) viewArea.dataset.dshMobileView = 'true'\n const conversation = center.querySelector<HTMLElement>('[data-conversation-scroll]')\n const messageColumn = conversation === null ? undefined : firstByClassSuffix(conversation, '_column')\n const messageScroll = messageColumn?.parentElement\n if (messageColumn !== undefined && messageScroll !== null && messageScroll !== undefined && classToken(messageScroll, '_scroll')) {\n messageColumn.dataset.dshMobileMessageColumn = 'true'\n messageScroll.dataset.dshMobileMessageScroll = 'true'\n }\n }\n if (handle !== undefined) handle.dataset.dshMobileHandle = 'true'\n if (details !== undefined) {\n details.dataset.dshMobileDetails = 'true'\n const lastColumn = frame?.style.gridTemplateColumns.trim().split(/\\s+/).at(-1)\n details.dataset.open = String(lastColumn !== undefined && lastColumn !== '0px' && lastColumn !== '0')\n }\n const settings = Array.from(document.querySelectorAll<HTMLElement>('[role=\"dialog\"]')).find(dialog => {\n const directNav = Array.from(dialog.children).find(child => child instanceof HTMLElement && classToken(child, '_nav'))\n return directNav !== undefined\n })\n if (settings !== undefined) {\n settings.dataset.dshMobileSettings = 'true'\n const nav = Array.from(settings.children).find(child => child instanceof HTMLElement && classToken(child, '_nav')) as HTMLElement | undefined\n const content = Array.from(settings.children).find(child => child instanceof HTMLElement && classToken(child, '_content')) as HTMLElement | undefined\n if (nav !== undefined) {\n nav.dataset.dshMobileSettingsNav = 'true'\n firstByClassSuffix(nav, '_navList')?.setAttribute('data-dsh-mobile-settings-list', 'true')\n }\n if (content !== undefined) {\n content.dataset.dshMobileSettingsContent = 'true'\n firstByClassSuffix(content, '_header')?.setAttribute('data-dsh-mobile-settings-header', 'true')\n firstByClassSuffix(content, '_options')?.setAttribute('data-dsh-mobile-settings-options', 'true')\n }\n }\n const textarea = center?.querySelector<HTMLTextAreaElement>('textarea')\n const card = textarea === null || textarea === undefined ? undefined : composerCard(textarea)\n const tools = card === undefined ? undefined : firstByClassSuffix(card, '_tools')\n attach.disabled = textarea === undefined || textarea === null || textarea.disabled || textarea.readOnly\n if (tools !== undefined && attach.parentElement !== tools) tools.append(attach)\n if (sidebar === undefined) return\n sidebar.dataset.dshMobileSidebar = 'true'\n toggle = firstByClassSuffix(sidebar, '_toggle') as HTMLButtonElement | undefined\n let candidate = toggle?.parentElement\n while (candidate !== undefined && candidate !== null && candidate !== sidebar && !classToken(candidate, '_root')) candidate = candidate.parentElement\n sidebarRoot = candidate !== sidebar && candidate !== null ? candidate : undefined\n if (sidebarRoot === undefined) return\n sidebarRoot.dataset.dshMobileSidebarRoot = 'true'\n if (toggle !== undefined) toggle.dataset.dshMobileToggle = 'true'\n const collapsed = classToken(sidebarRoot, '_collapsed')\n sidebar.dataset.open = String(!collapsed)\n backdrop.hidden = collapsed\n }\n const schedule = (): void => { if (scheduled === 0) scheduled = requestAnimationFrame(sync) }\n const observer = new MutationObserver(schedule)\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class', 'style'] })\n backdrop.addEventListener('click', () => { if (sidebar?.dataset.open === 'true') toggle?.click() })\n sync()\n return () => {\n observer.disconnect()\n if (scheduled !== 0) cancelAnimationFrame(scheduled)\n if (transitionFrame !== 0) cancelAnimationFrame(transitionFrame)\n if (transitionRestartFrame !== 0) cancelAnimationFrame(transitionRestartFrame)\n if (transitionTimer !== 0) clearTimeout(transitionTimer)\n transitionTarget?.removeAttribute('data-dsh-mobile-view-transition')\n document.removeEventListener('pointerdown', onPointerDown, true)\n document.removeEventListener('keydown', onKeyDown, true)\n document.removeEventListener('click', animateNavigation)\n backdrop.remove()\n attach.remove()\n fileInput.remove()\n sheet.remove()\n sheetMask.remove()\n document.documentElement.classList.remove('dsh-native-mobile-active')\n delete document.documentElement.dataset.dshMobileInput\n }\n}\n","import { createElement } from 'react'\nimport { installNativeMobileSurface, NATIVE_MOBILE_STYLES } from './native-mobile.js'\n\ninterface ClientContext {\n effect(effect: () => void | (() => void), label?: string): void\n slots: {\n inject(key: string, callback: () => (() => void)): () => void\n register(options: { name: string; id: string }, component: (props: { wide: boolean }) => unknown): () => void\n }\n}\n\ninterface MobileExtensionContext {\n readonly document: Document\n readonly request: (path: string, init?: RequestInit) => Promise<Response>\n readonly root: HTMLElement\n readonly window: Window\n}\n\ntype MobileExtensionMount = (context: MobileExtensionContext) => void | (() => void)\n\ndeclare global {\n interface Window {\n dshMobile?: { register(mount: MobileExtensionMount): void }\n __DSH_MOBILE_FRONTEND__?: 'dedicated'\n }\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1' || hostname === '[::1]'\n}\n\nfunction element<K extends keyof HTMLElementTagNameMap>(tag: K, className?: string): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag)\n if (className !== undefined) node.className = className\n return node\n}\n\nasync function requestJson(path: string, init?: RequestInit): Promise<Record<string, unknown>> {\n const response = await fetch(path, { ...init, headers: { 'content-type': 'application/json', ...init?.headers } })\n const body = await response.json() as Record<string, unknown>\n if (!response.ok) throw new Error(typeof body.error === 'string' ? body.error : `HTTP ${String(response.status)}`)\n return body\n}\n\nfunction installControl(): { remove: () => void; toggle: () => void } {\n const root = element('div', 'dsh-mobile-control')\n const panel = element('section', 'dsh-mobile-control__panel'); panel.hidden = true\n panel.setAttribute('aria-label', '移动访问')\n const header = element('header', 'dsh-mobile-control__header')\n const title = element('h2'); title.textContent = '移动访问'\n const close = element('button', 'dsh-mobile-control__close'); close.type = 'button'; close.textContent = '×'; close.setAttribute('aria-label', '收起移动访问')\n const access = element('div', 'dsh-mobile-control__access'); access.hidden = true\n const accessLabel = element('span', 'dsh-mobile-control__access-label'); accessLabel.textContent = '浏览器访问'\n const accessLink = element('a', 'dsh-mobile-control__access-link'); accessLink.target = '_blank'; accessLink.rel = 'noreferrer'\n access.append(accessLabel, accessLink)\n const status = element('p', 'dsh-mobile-control__status'); status.textContent = '正在读取状态…'\n const actions = element('div', 'dsh-mobile-control__actions')\n const toggle = element('button', 'dsh-mobile-control__secondary'); toggle.type = 'button'\n const pair = element('button', 'dsh-mobile-control__primary'); pair.type = 'button'; pair.textContent = '生成并复制密钥'\n header.append(title, close); actions.append(toggle, pair); panel.append(header, access, status, actions); root.append(panel); document.body.append(root)\n let running = false\n let origin = ''\n const setOpen = (open: boolean): void => {\n panel.hidden = !open\n for (const trigger of document.querySelectorAll('.dsh-mobile-control__trigger')) trigger.setAttribute('aria-expanded', String(open))\n }\n const render = (data: Record<string, unknown>): void => {\n running = data.running === true\n origin = running && typeof data.origin === 'string' ? data.origin : ''\n access.hidden = origin === ''\n accessLink.href = origin\n accessLink.textContent = origin\n accessLink.title = origin\n status.classList.toggle('is-running', running)\n status.textContent = running ? '移动访问已开启。' : '已关闭。DSH 仍只在本机可用。'\n toggle.textContent = running ? '关闭移动访问' : '开启移动访问'; pair.disabled = !running\n }\n toggle.addEventListener('click', () => { toggle.disabled = true; void requestJson('/api/mobile-access/control', { method: 'POST', body: JSON.stringify({ running: !running }) }).then(render, error => { status.textContent = String(error) }).finally(() => { toggle.disabled = false }) })\n pair.addEventListener('click', () => { pair.disabled = true; void requestJson('/api/mobile-access/pairing/open', { method: 'POST', body: '{}' }).then(async data => {\n const key = typeof data.appKey === 'string' ? data.appKey : ''\n if (key === '') { status.textContent = '无法生成配对密钥。'; return }\n try {\n await navigator.clipboard.writeText(key)\n status.textContent = '配对密钥已复制,请粘贴到 Android App。'\n } catch {\n status.textContent = `请复制配对密钥:${key}`\n status.classList.add('is-key')\n }\n }, error => { status.textContent = String(error) }).finally(() => { pair.disabled = !running }) })\n close.addEventListener('click', () => { setOpen(false) })\n const dismiss = (event: PointerEvent): void => {\n if (panel.hidden || !(event.target instanceof Node)) return\n if (!panel.contains(event.target) && !document.querySelector('.dsh-mobile-control__trigger')?.contains(event.target)) setOpen(false)\n }\n document.addEventListener('pointerdown', dismiss)\n void requestJson('/api/mobile-access/control').then(render, error => { status.textContent = String(error) })\n return { remove: () => { document.removeEventListener('pointerdown', dismiss); root.remove() }, toggle: () => { setOpen(panel.hidden !== false) } }\n}\n\nfunction mobileRequest(path: string, init: RequestInit = {}): Promise<Response> {\n const target = new URL(path, location.href)\n if (target.origin !== location.origin) throw new TypeError('mobile extension requests must stay on the DSH origin')\n const headers = new Headers(init.headers)\n const method = (init.method ?? 'GET').toUpperCase()\n if (method !== 'GET' && method !== 'HEAD') {\n const csrf = document.cookie.split(';').map(value => value.trim()).find(value => value.startsWith('dsh_ma_csrf='))?.slice(12)\n if (csrf !== undefined) headers.set('x-dsh-mobile-csrf', csrf)\n }\n return fetch(target, { ...init, headers, credentials: 'same-origin', cache: 'no-store', redirect: 'error' })\n}\n\nfunction installCustomAssets(): () => void {\n const style = element('style'); style.dataset.plugin = 'dsh-mobile-custom'; document.head.append(style)\n let cssLoading = false\n const refreshCss = async (): Promise<void> => { if (cssLoading || document.visibilityState === 'hidden') return; cssLoading = true; try { const response = await fetch('/mobile-access/custom.css', { cache: 'no-store', credentials: 'same-origin' }); if (response.ok) { const css = await response.text(); if (style.textContent !== css) style.textContent = css } } finally { cssLoading = false } }\n let activeRoot: HTMLElement | undefined; let disposeActive: (() => void) | undefined; let source = ''; let pending: MobileExtensionMount | undefined\n const previous = window.dshMobile\n window.dshMobile = Object.freeze({ register: (mount: MobileExtensionMount) => { pending = mount } })\n const registeredMount = (): MobileExtensionMount | undefined => pending\n const refreshJs = async (): Promise<void> => { try { const response = await fetch('/mobile-access/custom.js', { cache: 'no-store', credentials: 'same-origin' }); if (!response.ok) return; const next = await response.text(); if (next === source) return; source = next; pending = undefined; const script = element('script'); script.textContent = `${next}\\n//# sourceURL=dsh-mobile-custom.js`; document.head.append(script); script.remove(); const mount = registeredMount(); if (mount === undefined) return; const nextRoot = element('div'); nextRoot.dataset.dshMobileExtension = 'true'; document.body.append(nextRoot); const nextDispose = mount({ document, request: mobileRequest, root: nextRoot, window }); disposeActive?.(); activeRoot?.remove(); activeRoot = nextRoot; disposeActive = typeof nextDispose === 'function' ? nextDispose : undefined } catch { /* Preserve the last good customization during reconnects. */ } }\n void refreshCss(); void refreshJs()\n const timer = window.setInterval(() => { void refreshCss(); void refreshJs() }, 1_000)\n return () => { clearInterval(timer); disposeActive?.(); activeRoot?.remove(); style.remove(); if (previous === undefined) delete window.dshMobile; else window.dshMobile = previous }\n}\n\nconst CONTROL_STYLES = `\n.dsh-mobile-control{position:fixed;z-index:1000;left:16px;bottom:64px;font:14px/1.45 system-ui;color:var(--dsw-alias-label-primary,#16181d)}\n.dsh-mobile-control__panel{box-sizing:border-box;width:min(328px,calc(100vw - 32px));padding:16px;border:1px solid var(--dsw-alias-border-subtle,#e1e5eb);border-radius:18px;background:var(--dsw-alias-bg-layer-2,#fff);box-shadow:0 18px 50px rgb(15 23 42 / 18%)}\n.dsh-mobile-control__header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:10px}.dsh-mobile-control__panel h2{margin:0;font-size:17px;line-height:24px}.dsh-mobile-control__close{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:0;border-radius:10px;background:transparent;color:inherit;font-size:24px;line-height:1;cursor:pointer}.dsh-mobile-control__close:hover{background:var(--dsw-alias-interactive-bg-hover,#f1f3f6)}\n.dsh-mobile-control__access{display:flex;align-items:baseline;gap:6px;min-width:0;margin:0 0 12px}.dsh-mobile-control__access[hidden]{display:none}.dsh-mobile-control__access-label{flex:none;color:var(--dsw-alias-label-secondary,#606873);white-space:nowrap}.dsh-mobile-control__access-label::after{content:\":\"}.dsh-mobile-control__access-link{min-width:0;overflow:hidden;color:#2563eb;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.dsh-mobile-control__access-link:hover{text-decoration:underline}\n.dsh-mobile-control__status{margin:0 0 14px;overflow-wrap:anywhere;color:var(--dsw-alias-label-secondary,#606873)}.dsh-mobile-control__status::before{display:inline-block;width:8px;height:8px;margin-right:7px;border-radius:50%;background:#98a1ad;content:\"\"}.dsh-mobile-control__status.is-running::before{background:#16a36a}.dsh-mobile-control__status.is-key{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:12px;word-break:break-all}\n.dsh-mobile-control__actions{display:flex;flex-wrap:wrap;gap:8px}.dsh-mobile-control__actions button{min-height:40px;padding:8px 12px;border-radius:11px;font:inherit;cursor:pointer}.dsh-mobile-control__secondary{border:1px solid var(--dsw-alias-border-normal,#cfd5dd);background:transparent;color:inherit}.dsh-mobile-control__primary{border:1px solid #2563eb;background:#2563eb;color:#fff}.dsh-mobile-control__actions button:disabled{cursor:not-allowed;opacity:.45}\n.dsh-mobile-control__trigger{box-sizing:border-box;display:flex;align-items:center;gap:8px;width:calc(100% + 8px);height:34px;margin:4px -4px;padding:6px 2px 6px 10px;border:0;border-radius:12px;background:transparent;color:var(--dsw-alias-label-primary,#16181d);font:14px/22px system-ui;cursor:pointer}.dsh-mobile-control__trigger:hover{background:var(--dsw-alias-interactive-bg-hover,#f1f3f6)}.dsh-mobile-control__trigger.is-rail{width:36px;height:36px;margin:8px 0 10px;padding:0;justify-content:center;border-radius:50%}.dsh-mobile-control__trigger-icon{position:relative;box-sizing:border-box;flex:none;width:14px;height:19px;border:1.7px solid currentColor;border-radius:3px}.dsh-mobile-control__trigger-icon::after{position:absolute;right:4px;bottom:2px;width:4px;height:1.5px;border-radius:2px;background:currentColor;content:\"\"}.dsh-mobile-control__trigger-label{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}\n`\n\n/** Mount the desktop control or mobile feature enhancements. */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => {\n const loopback = isLoopbackHost(location.hostname) && !new URLSearchParams(location.search).has('dsh-mobile-preview')\n const style = element('style'); style.dataset.plugin = 'dsh-mobile'; style.textContent = loopback\n ? CONTROL_STYLES\n : NATIVE_MOBILE_STYLES\n document.head.append(style)\n if (!loopback) {\n const removeCustom = installCustomAssets()\n const removeSurface = installNativeMobileSurface()\n return () => { removeCustom(); removeSurface(); style.remove() }\n }\n const control = installControl()\n const disposeSlot = ctx.slots.inject('sidebar.footer.action', () => ctx.slots.register({ name: 'sidebar.footer.action', id: 'dsh-mobile' }, ({ wide }) => createElement('button', {\n 'aria-expanded': false,\n 'aria-label': '移动访问',\n className: `dsh-mobile-control__trigger${wide ? '' : ' is-rail'}`,\n type: 'button',\n title: '移动访问',\n onClick: control.toggle,\n }, createElement('span', { 'aria-hidden': true, className: 'dsh-mobile-control__trigger-icon' }), wide ? createElement('span', { className: 'dsh-mobile-control__trigger-label' }, '移动访问') : undefined)))\n return () => { disposeSlot(); control.remove(); style.remove() }\n }, 'dsh-mobile: stock mobile adaptation and local control')\n}\n\n/** Client services required by the mobile adaptation. */\nexport const inject: readonly string[] = ['slots']\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["createElement"],"sources":["../src/native-mobile.ts","../src/client.ts"],"sourcesContent":["/** Mobile feature and compatibility rules applied to DSH React surfaces. */\nexport const NATIVE_MOBILE_STYLES = `\n@media (max-width:720px) {\n html.dsh-native-mobile-active,html.dsh-native-mobile-active body { width:100%; height:100%; overflow:hidden; }\n html.dsh-native-mobile-active { --dsh-mobile-motion-duration:200ms; --dsh-mobile-motion-ease:cubic-bezier(.22,1,.36,1); }\n html.dsh-native-mobile-active :is(a,button,[role=\"button\"],[role=\"tab\"],[tabindex]) { -webkit-tap-highlight-color:transparent; }\n html.dsh-native-mobile-active[data-dsh-mobile-input=\"touch\"] :is(a,button,[role=\"button\"],[role=\"tab\"],[tabindex]):focus { outline:none !important; }\n [data-dsh-mobile-frame] { grid-template-columns:0 minmax(0,1fr) 0 !important; width:100% !important; height:100dvh !important; overflow:hidden !important; }\n [data-dsh-mobile-center] { grid-column:2 !important; width:100vw !important; min-width:0 !important; }\n [data-dsh-mobile-center] > * { min-width:0 !important; }\n [data-dsh-mobile-header] { min-width:0; padding-right:12px !important; padding-left:50px !important; }\n [data-dsh-mobile-header] [class*=\"_titleRow\"] { box-sizing:border-box !important; min-width:0; min-height:52px !important; height:52px !important; gap:6px !important; padding:4px 8px !important; }\n [data-dsh-mobile-header] [class*=\"_titleCluster\"] { min-width:0; }\n [data-dsh-mobile-header] [class*=\"_crumbs\"] { min-width:0; overflow:hidden; }\n [data-dsh-mobile-header] [class*=\"_crumb\"] { max-width:46vw; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n [data-dsh-mobile-header] [class*=\"_headerActions\"] { min-width:0; overflow-x:auto; scrollbar-width:none; }\n [data-dsh-mobile-header] [class*=\"_headerActions\"]::-webkit-scrollbar { display:none; }\n [data-dsh-mobile-header] [class*=\"_headerUtilities\"] { gap:2px !important; }\n [data-dsh-mobile-header] [class*=\"_sessionLogButton\"] { width:40px; min-width:40px; padding:0 !important; overflow:hidden; color:transparent; font-size:0 !important; }\n [data-dsh-mobile-header] [class*=\"_sessionLogButton\"] > * { display:none !important; }\n [data-dsh-mobile-header] [class*=\"_sessionLogButton\"]::after { color:var(--dsw-text, #171a21); content:\"日志\"; font-size:11px; font-weight:600; }\n [data-dsh-mobile-header] [class*=\"_tabs\"] { min-height:42px; overflow-x:auto; scrollbar-width:none; }\n [data-dsh-mobile-header] [class*=\"_tabs\"]::-webkit-scrollbar { display:none; }\n [data-dsh-mobile-sidebar] { position:fixed !important; z-index:240 !important; inset:0 auto 0 0 !important; width:0 !important; overflow:visible !important; }\n [data-dsh-mobile-sidebar-root] { position:fixed !important; z-index:241 !important; inset:0 auto 0 0 !important; height:100dvh !important; transition:transform var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease) !important; }\n [data-dsh-mobile-sidebar][data-open=\"true\"] [data-dsh-mobile-sidebar-root] { width:min(88vw,340px) !important; box-shadow:18px 0 46px rgb(15 23 42 / 18%); }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] { width:0 !important; border:0 !important; background:transparent !important; box-shadow:none !important; overflow:visible !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] > :not(:has([data-dsh-mobile-toggle])) { display:none !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] > :has([data-dsh-mobile-toggle]) { position:fixed !important; z-index:244 !important; top:env(safe-area-inset-top) !important; left:0 !important; width:50px !important; height:52px !important; padding:4px !important; border:0 !important; background:transparent !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-sidebar-root] > :has([data-dsh-mobile-toggle]) > :not([data-dsh-mobile-toggle]) { display:none !important; }\n [data-dsh-mobile-toggle] { width:44px !important; height:44px !important; min-width:44px !important; min-height:44px !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-toggle] svg { display:none !important; }\n [data-dsh-mobile-sidebar][data-open=\"false\"] [data-dsh-mobile-toggle]::after { width:20px; height:2px; border-radius:2px; background:currentColor; box-shadow:0 -6px 0 currentColor,0 6px 0 currentColor; content:\"\"; }\n .dsh-native-mobile-backdrop { position:fixed; z-index:235; inset:0; border:0; background:rgb(15 23 42 / 32%); }\n .dsh-native-mobile-backdrop:not([hidden]) { animation:dsh-mobile-fade-in var(--dsh-mobile-motion-duration) ease-out; }\n .dsh-native-mobile-backdrop[hidden] { display:none; }\n [data-dsh-mobile-details] { position:fixed !important; z-index:250 !important; inset:0 0 0 auto !important; width:min(94vw,460px) !important; max-width:none !important; transform:translateX(100%); transition:transform var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease); background:var(--dsw-bg, #fff); box-shadow:-18px 0 46px rgb(15 23 42 / 18%); }\n [data-dsh-mobile-details][data-open=\"true\"] { transform:translateX(0); }\n [data-dsh-mobile-handle] { display:none !important; }\n [data-dsh-mobile-settings] { flex-direction:column !important; width:100vw !important; height:100dvh !important; max-width:none !important; border-radius:0 !important; animation:dsh-mobile-panel-in var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease); }\n [data-dsh-mobile-settings-nav] { flex:none !important; width:100% !important; padding:max(14px,env(safe-area-inset-top)) 12px 8px !important; gap:10px !important; border-bottom:1px solid var(--dsw-alias-border-subtle,#e8ebef); }\n [data-dsh-mobile-settings-nav] [class*=\"_navTitle\"] { padding:0 8px !important; font-size:18px !important; line-height:28px !important; }\n [data-dsh-mobile-settings-list] { flex-direction:row !important; gap:4px !important; overflow-x:auto !important; scrollbar-width:none; }\n [data-dsh-mobile-settings-list]::-webkit-scrollbar { display:none; }\n [data-dsh-mobile-settings-list] [class*=\"_navCell\"] { flex:0 0 auto !important; min-width:max-content !important; height:44px !important; padding:10px 12px !important; }\n [data-dsh-mobile-settings-list] [aria-current=\"true\"] { border-color:transparent !important; outline:0 !important; box-shadow:none !important; }\n [data-dsh-mobile-settings-content] { flex:1 1 auto !important; width:100% !important; min-height:0 !important; }\n [data-dsh-mobile-settings-header] { height:48px !important; min-height:48px !important; padding:10px 12px 6px !important; }\n [data-dsh-mobile-settings-header] [class*=\"_close\"] { width:36px !important; height:36px !important; }\n [data-dsh-mobile-settings-options] { box-sizing:border-box !important; width:100% !important; padding:4px 16px max(24px,env(safe-area-inset-bottom)) !important; overflow-x:hidden !important; }\n [data-dsh-mobile-settings-options] > * { width:100% !important; min-width:0 !important; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] > [class*=\"_row\"] { flex-direction:column !important; align-items:stretch !important; gap:12px !important; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] [class*=\"_rowText\"] { width:100% !important; padding-right:0 !important; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] [class*=\"_selector\"] { box-sizing:border-box !important; align-self:flex-start !important; justify-content:space-between !important; min-width:0 !important; min-height:44px !important; max-width:100% !important; }\n [data-dsh-mobile-settings-options] :is(input,select,textarea,button) { max-width:100%; }\n [data-dsh-mobile-settings-options] :is(input,select,textarea) { box-sizing:border-box; width:100%; min-width:0; }\n [data-dsh-mobile-settings-options] [class*=\"_head\"] { min-width:0; flex-wrap:wrap; }\n [data-dsh-mobile-settings-content][data-dsh-mobile-view-transition=\"true\"],\n [data-dsh-mobile-view][data-dsh-mobile-view-transition=\"true\"] { animation:dsh-mobile-view-in var(--dsh-mobile-motion-duration) var(--dsh-mobile-motion-ease); }\n [data-dsh-mobile-center] textarea { font-size:16px !important; }\n [data-dsh-mobile-center] table { display:block; max-width:100%; overflow-x:auto; }\n [data-dsh-mobile-center] pre { max-width:100%; overflow-x:auto; }\n [data-dsh-mobile-center] :is(img,video,canvas,svg) { max-width:100%; }\n [data-dsh-mobile-message-scroll] { box-sizing:border-box !important; width:100% !important; padding:12px 16px 20px !important; }\n [data-dsh-mobile-message-column] { box-sizing:border-box !important; width:100% !important; max-width:none !important; margin:0 !important; padding:0 !important; gap:14px !important; }\n [data-dsh-mobile-message-column] > * { width:100% !important; max-width:100% !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] { box-sizing:border-box !important; display:grid !important; grid-template-columns:16px minmax(0,1fr) !important; grid-auto-rows:auto !important; align-items:center !important; column-gap:6px !important; width:100% !important; height:auto !important; min-height:44px !important; padding:5px 0 !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > [class*=\"_leading\"] { grid-column:1 !important; grid-row:1 !important; margin-right:0 !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > [class*=\"_title\"] { grid-column:2 !important; grid-row:1 !important; min-width:0 !important; overflow:hidden !important; text-overflow:ellipsis !important; white-space:nowrap !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > :is([class*=\"_sep\"],[class*=\"_separator\"]) { display:none !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > :is([class*=\"_summary\"],[class*=\"_fileLink\"]) { grid-column:2 !important; grid-row:2 !important; width:100% !important; min-width:0 !important; max-width:100% !important; overflow:hidden !important; line-height:20px !important; text-overflow:ellipsis !important; white-space:nowrap !important; }\n [data-dsh-mobile-message-column] [data-disclosure-row] > [class*=\"_summarySuffix\"] { grid-column:2 !important; grid-row:3 !important; margin-left:0 !important; }\n [data-dsh-mobile-message-column] [data-context-fields] > * { display:grid !important; grid-template-columns:minmax(72px,30%) minmax(0,1fr) !important; gap:4px 10px !important; }\n [data-dsh-mobile-message-column] [class*=\"_ioSection\"] { grid-template-columns:1fr !important; row-gap:4px !important; }\n [data-dsh-mobile-message-column] [class*=\"_body\"] { max-width:100% !important; overflow-wrap:anywhere; }\n [data-dsh-mobile-center] [class*=\"_composer\"] { padding-left:8px !important; padding-right:8px !important; padding-bottom:max(8px,env(safe-area-inset-bottom)) !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_row\"] { display:flex !important; align-items:center !important; gap:4px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_tools\"] { flex:0 0 auto !important; width:auto !important; min-width:0 !important; gap:6px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_trailing\"] { flex:1 1 auto !important; min-width:0 !important; gap:6px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) [class*=\"_trailing\"] [class*=\"_root\"]:has(button[aria-label^=\"选择模型\"]) { flex:1 1 auto !important; min-width:0 !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) button[aria-label^=\"选择模型\"] { width:100% !important; min-width:0 !important; padding-left:6px !important; padding-right:4px !important; }\n [data-dsh-mobile-center] [class*=\"_card\"]:has(textarea) button[aria-label^=\"选择模型\"] [class*=\"_triggerLabel\"] { max-width:78px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n [data-dsh-mobile-center] [class*=\"_root\"]:has(> [class*=\"_card\"] textarea) { box-sizing:border-box !important; width:100% !important; padding:0 0 8px !important; }\n [data-dsh-mobile-center] [class*=\"_root\"]:has(> [class*=\"_card\"] textarea) > [class=\"\"]:last-child { display:none !important; }\n}\n@keyframes dsh-mobile-fade-in { from { opacity:0; } }\n@keyframes dsh-mobile-panel-in { from { opacity:.72; transform:translateY(6px); } }\n@keyframes dsh-mobile-view-in { from { opacity:.58; transform:translateY(5px); } }\n@media (max-width:420px) {\n [data-dsh-mobile-header] [class*=\"_headerActions\"] { max-width:42vw; }\n [data-dsh-mobile-header] [class*=\"_titleRow\"] { min-height:50px; }\n [data-dsh-mobile-settings-options] [data-slot=\"settings.general.item\"] [class*=\"_selector\"] { align-self:stretch !important; width:100% !important; }\n [data-dsh-mobile-message-column] [data-context-fields] > * { grid-template-columns:1fr !important; }\n}\n@media (prefers-reduced-motion:reduce) {\n [data-dsh-mobile-sidebar-root],[data-dsh-mobile-details] { transition:none !important; }\n .dsh-native-mobile-backdrop:not([hidden]),[data-dsh-mobile-settings],\n [data-dsh-mobile-settings-content][data-dsh-mobile-view-transition=\"true\"],\n [data-dsh-mobile-view][data-dsh-mobile-view-transition=\"true\"] { animation:none !important; }\n}\n`\n\nfunction classToken(element: Element, suffix: string): boolean {\n return Array.from(element.classList).some(value => value.endsWith(suffix))\n}\n\nfunction firstByClassSuffix(root: ParentNode, suffix: string): HTMLElement | undefined {\n return Array.from(root.querySelectorAll<HTMLElement>('[class]')).find(element => classToken(element, suffix))\n}\n\n/** Add mobile semantics without replacing feature trees. */\nexport function installNativeMobileSurface(): () => void {\n document.documentElement.classList.add('dsh-native-mobile-active')\n const setInputMode = (mode: 'keyboard' | 'touch'): void => {\n document.documentElement.dataset.dshMobileInput = mode\n }\n const onPointerDown = (event: PointerEvent): void => {\n if (event.pointerType === 'touch' || event.pointerType === 'pen') setInputMode('touch')\n }\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key === 'Tab' || event.key.startsWith('Arrow')) setInputMode('keyboard')\n }\n document.addEventListener('pointerdown', onPointerDown, true)\n document.addEventListener('keydown', onKeyDown, true)\n const backdrop = document.createElement('button')\n backdrop.type = 'button'\n backdrop.className = 'dsh-native-mobile-backdrop'\n backdrop.hidden = true\n backdrop.setAttribute('aria-label', '关闭工作区导航')\n document.body.append(backdrop)\n let frame: HTMLElement | undefined\n let sidebar: HTMLElement | undefined\n let sidebarRoot: HTMLElement | undefined\n let toggle: HTMLButtonElement | undefined\n let viewArea: HTMLElement | undefined\n let scheduled = 0\n let transitionFrame = 0\n let transitionRestartFrame = 0\n let transitionTimer = 0\n let transitionTarget: HTMLElement | undefined\n const animateNavigation = (event: MouseEvent): void => {\n if (!(event.target instanceof Element)) return\n const trigger = event.target.closest<HTMLElement>('button,a,[role=\"tab\"],[aria-selected]')\n if (trigger === null || trigger.hasAttribute('disabled') || trigger.getAttribute('aria-disabled') === 'true') return\n if (trigger.getAttribute('aria-selected') === 'true' || trigger.getAttribute('aria-current') === 'true') return\n const settingsNavigation = trigger.closest('[data-dsh-mobile-settings-list]') !== null\n const conversationNavigation = trigger.matches('[role=\"tab\"]')\n const sidebarNavigation = trigger.closest('[data-dsh-mobile-sidebar-root]') !== null\n && trigger.closest('[data-dsh-mobile-toggle]') === null\n if (!settingsNavigation && !conversationNavigation && !sidebarNavigation) return\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return\n if (transitionFrame !== 0) cancelAnimationFrame(transitionFrame)\n if (transitionRestartFrame !== 0) cancelAnimationFrame(transitionRestartFrame)\n transitionFrame = requestAnimationFrame(() => {\n transitionFrame = 0\n const target = settingsNavigation\n ? document.querySelector<HTMLElement>('[data-dsh-mobile-settings-content]')\n : viewArea\n if (target === null || target === undefined) return\n transitionTarget?.removeAttribute('data-dsh-mobile-view-transition')\n target.removeAttribute('data-dsh-mobile-view-transition')\n transitionRestartFrame = requestAnimationFrame(() => {\n transitionRestartFrame = 0\n transitionTarget = target\n target.dataset.dshMobileViewTransition = 'true'\n if (transitionTimer !== 0) clearTimeout(transitionTimer)\n transitionTimer = window.setTimeout(() => {\n target.removeAttribute('data-dsh-mobile-view-transition')\n if (transitionTarget === target) transitionTarget = undefined\n transitionTimer = 0\n }, 240)\n })\n })\n }\n document.addEventListener('click', animateNavigation)\n\n const sync = (): void => {\n scheduled = 0\n frame = firstByClassSuffix(document, '_frame')\n const dedicatedCenter = document.querySelector<HTMLElement>('.dshm-main') ?? undefined\n if (frame !== undefined) frame.dataset.dshMobileFrame = 'true'\n sidebar = frame === undefined ? undefined : firstByClassSuffix(frame, '_sidebarCol')\n const center = frame === undefined ? dedicatedCenter : firstByClassSuffix(frame, '_centerCol')\n const details = frame === undefined ? undefined : firstByClassSuffix(frame, '_detailsCol')\n const handle = frame === undefined ? undefined : firstByClassSuffix(frame, '_handle')\n if (center === undefined) return\n if (center !== undefined) {\n center.dataset.dshMobileCenter = 'true'\n center.querySelector<HTMLElement>('header')?.setAttribute('data-dsh-mobile-header', 'true')\n viewArea = firstByClassSuffix(center, '_viewArea')\n if (viewArea !== undefined) viewArea.dataset.dshMobileView = 'true'\n const conversation = center.querySelector<HTMLElement>('[data-conversation-scroll]')\n const messageColumn = conversation === null ? undefined : firstByClassSuffix(conversation, '_column')\n const messageScroll = messageColumn?.parentElement\n if (messageColumn !== undefined && messageScroll !== null && messageScroll !== undefined && classToken(messageScroll, '_scroll')) {\n messageColumn.dataset.dshMobileMessageColumn = 'true'\n messageScroll.dataset.dshMobileMessageScroll = 'true'\n }\n }\n if (handle !== undefined) handle.dataset.dshMobileHandle = 'true'\n if (details !== undefined) {\n details.dataset.dshMobileDetails = 'true'\n const lastColumn = frame?.style.gridTemplateColumns.trim().split(/\\s+/).at(-1)\n details.dataset.open = String(lastColumn !== undefined && lastColumn !== '0px' && lastColumn !== '0')\n }\n const settings = Array.from(document.querySelectorAll<HTMLElement>('[role=\"dialog\"]')).find(dialog => {\n const directNav = Array.from(dialog.children).find(child => child instanceof HTMLElement && classToken(child, '_nav'))\n return directNav !== undefined\n })\n if (settings !== undefined) {\n settings.dataset.dshMobileSettings = 'true'\n const nav = Array.from(settings.children).find(child => child instanceof HTMLElement && classToken(child, '_nav')) as HTMLElement | undefined\n const content = Array.from(settings.children).find(child => child instanceof HTMLElement && classToken(child, '_content')) as HTMLElement | undefined\n if (nav !== undefined) {\n nav.dataset.dshMobileSettingsNav = 'true'\n firstByClassSuffix(nav, '_navList')?.setAttribute('data-dsh-mobile-settings-list', 'true')\n }\n if (content !== undefined) {\n content.dataset.dshMobileSettingsContent = 'true'\n firstByClassSuffix(content, '_header')?.setAttribute('data-dsh-mobile-settings-header', 'true')\n firstByClassSuffix(content, '_options')?.setAttribute('data-dsh-mobile-settings-options', 'true')\n }\n }\n if (sidebar === undefined) return\n sidebar.dataset.dshMobileSidebar = 'true'\n toggle = firstByClassSuffix(sidebar, '_toggle') as HTMLButtonElement | undefined\n let candidate = toggle?.parentElement\n while (candidate !== undefined && candidate !== null && candidate !== sidebar && !classToken(candidate, '_root')) candidate = candidate.parentElement\n sidebarRoot = candidate !== sidebar && candidate !== null ? candidate : undefined\n if (sidebarRoot === undefined) return\n sidebarRoot.dataset.dshMobileSidebarRoot = 'true'\n if (toggle !== undefined) toggle.dataset.dshMobileToggle = 'true'\n const collapsed = classToken(sidebarRoot, '_collapsed')\n sidebar.dataset.open = String(!collapsed)\n backdrop.hidden = collapsed\n }\n const schedule = (): void => { if (scheduled === 0) scheduled = requestAnimationFrame(sync) }\n const observer = new MutationObserver(schedule)\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class', 'style'] })\n backdrop.addEventListener('click', () => { if (sidebar?.dataset.open === 'true') toggle?.click() })\n sync()\n return () => {\n observer.disconnect()\n if (scheduled !== 0) cancelAnimationFrame(scheduled)\n if (transitionFrame !== 0) cancelAnimationFrame(transitionFrame)\n if (transitionRestartFrame !== 0) cancelAnimationFrame(transitionRestartFrame)\n if (transitionTimer !== 0) clearTimeout(transitionTimer)\n transitionTarget?.removeAttribute('data-dsh-mobile-view-transition')\n document.removeEventListener('pointerdown', onPointerDown, true)\n document.removeEventListener('keydown', onKeyDown, true)\n document.removeEventListener('click', animateNavigation)\n backdrop.remove()\n document.documentElement.classList.remove('dsh-native-mobile-active')\n delete document.documentElement.dataset.dshMobileInput\n }\n}\n","import { createElement } from 'react'\nimport { installNativeMobileSurface, NATIVE_MOBILE_STYLES } from './native-mobile.js'\n\ninterface ClientContext {\n effect(effect: () => void | (() => void), label?: string): void\n slots: {\n inject(key: string, callback: () => (() => void)): () => void\n register(options: { name: string; id: string }, component: (props: { wide: boolean }) => unknown): () => void\n }\n}\n\ninterface MobileExtensionContext {\n readonly document: Document\n readonly request: (path: string, init?: RequestInit) => Promise<Response>\n readonly root: HTMLElement\n readonly window: Window\n}\n\ntype MobileExtensionMount = (context: MobileExtensionContext) => void | (() => void)\n\ndeclare global {\n interface Window {\n dshMobile?: { register(mount: MobileExtensionMount): void }\n __DSH_MOBILE_FRONTEND__?: 'dedicated'\n }\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1' || hostname === '[::1]'\n}\n\nfunction element<K extends keyof HTMLElementTagNameMap>(tag: K, className?: string): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag)\n if (className !== undefined) node.className = className\n return node\n}\n\nasync function requestJson(path: string, init?: RequestInit): Promise<Record<string, unknown>> {\n const response = await fetch(path, { ...init, headers: { 'content-type': 'application/json', ...init?.headers } })\n const body = await response.json() as Record<string, unknown>\n if (!response.ok) throw new Error(typeof body.error === 'string' ? body.error : `HTTP ${String(response.status)}`)\n return body\n}\n\nfunction installControl(): { remove: () => void; toggle: () => void } {\n const root = element('div', 'dsh-mobile-control')\n const panel = element('section', 'dsh-mobile-control__panel'); panel.hidden = true\n panel.setAttribute('aria-label', '移动访问')\n const header = element('header', 'dsh-mobile-control__header')\n const title = element('h2'); title.textContent = '移动访问'\n const close = element('button', 'dsh-mobile-control__close'); close.type = 'button'; close.textContent = '×'; close.setAttribute('aria-label', '收起移动访问')\n const access = element('div', 'dsh-mobile-control__access'); access.hidden = true\n const accessLabel = element('span', 'dsh-mobile-control__access-label'); accessLabel.textContent = '浏览器访问'\n const accessLink = element('a', 'dsh-mobile-control__access-link'); accessLink.target = '_blank'; accessLink.rel = 'noreferrer'\n access.append(accessLabel, accessLink)\n const status = element('p', 'dsh-mobile-control__status'); status.textContent = '正在读取状态…'\n const actions = element('div', 'dsh-mobile-control__actions')\n const toggle = element('button', 'dsh-mobile-control__secondary'); toggle.type = 'button'\n const pair = element('button', 'dsh-mobile-control__primary'); pair.type = 'button'; pair.textContent = '生成并复制密钥'\n header.append(title, close); actions.append(toggle, pair); panel.append(header, access, status, actions); root.append(panel); document.body.append(root)\n let running = false\n let origin = ''\n const setOpen = (open: boolean): void => {\n panel.hidden = !open\n for (const trigger of document.querySelectorAll('.dsh-mobile-control__trigger')) trigger.setAttribute('aria-expanded', String(open))\n }\n const render = (data: Record<string, unknown>): void => {\n running = data.running === true\n origin = running && typeof data.origin === 'string' ? data.origin : ''\n access.hidden = origin === ''\n accessLink.href = origin\n accessLink.textContent = origin\n accessLink.title = origin\n status.classList.toggle('is-running', running)\n status.textContent = running ? '移动访问已开启。' : '已关闭。DSH 仍只在本机可用。'\n toggle.textContent = running ? '关闭移动访问' : '开启移动访问'; pair.disabled = !running\n }\n toggle.addEventListener('click', () => { toggle.disabled = true; void requestJson('/api/mobile-access/control', { method: 'POST', body: JSON.stringify({ running: !running }) }).then(render, error => { status.textContent = String(error) }).finally(() => { toggle.disabled = false }) })\n pair.addEventListener('click', () => { pair.disabled = true; void requestJson('/api/mobile-access/pairing/open', { method: 'POST', body: '{}' }).then(async data => {\n const key = typeof data.appKey === 'string' ? data.appKey : ''\n if (key === '') { status.textContent = '无法生成配对密钥。'; return }\n try {\n await navigator.clipboard.writeText(key)\n status.textContent = '配对密钥已复制,请粘贴到 Android App。'\n } catch {\n status.textContent = `请复制配对密钥:${key}`\n status.classList.add('is-key')\n }\n }, error => { status.textContent = String(error) }).finally(() => { pair.disabled = !running }) })\n close.addEventListener('click', () => { setOpen(false) })\n const dismiss = (event: PointerEvent): void => {\n if (panel.hidden || !(event.target instanceof Node)) return\n if (!panel.contains(event.target) && !document.querySelector('.dsh-mobile-control__trigger')?.contains(event.target)) setOpen(false)\n }\n document.addEventListener('pointerdown', dismiss)\n void requestJson('/api/mobile-access/control').then(render, error => { status.textContent = String(error) })\n return { remove: () => { document.removeEventListener('pointerdown', dismiss); root.remove() }, toggle: () => { setOpen(panel.hidden !== false) } }\n}\n\nfunction mobileRequest(path: string, init: RequestInit = {}): Promise<Response> {\n const target = new URL(path, location.href)\n if (target.origin !== location.origin) throw new TypeError('mobile extension requests must stay on the DSH origin')\n const headers = new Headers(init.headers)\n const method = (init.method ?? 'GET').toUpperCase()\n if (method !== 'GET' && method !== 'HEAD') {\n const csrf = document.cookie.split(';').map(value => value.trim()).find(value => value.startsWith('dsh_ma_csrf='))?.slice(12)\n if (csrf !== undefined) headers.set('x-dsh-mobile-csrf', csrf)\n }\n return fetch(target, { ...init, headers, credentials: 'same-origin', cache: 'no-store', redirect: 'error' })\n}\n\nfunction installCustomAssets(): () => void {\n const style = element('style'); style.dataset.plugin = 'dsh-mobile-custom'; document.head.append(style)\n let cssLoading = false\n const refreshCss = async (): Promise<void> => { if (cssLoading || document.visibilityState === 'hidden') return; cssLoading = true; try { const response = await fetch('/mobile-access/custom.css', { cache: 'no-store', credentials: 'same-origin' }); if (response.ok) { const css = await response.text(); if (style.textContent !== css) style.textContent = css } } finally { cssLoading = false } }\n let activeRoot: HTMLElement | undefined; let disposeActive: (() => void) | undefined; let source = ''; let pending: MobileExtensionMount | undefined\n const previous = window.dshMobile\n window.dshMobile = Object.freeze({ register: (mount: MobileExtensionMount) => { pending = mount } })\n const registeredMount = (): MobileExtensionMount | undefined => pending\n const refreshJs = async (): Promise<void> => { try { const response = await fetch('/mobile-access/custom.js', { cache: 'no-store', credentials: 'same-origin' }); if (!response.ok) return; const next = await response.text(); if (next === source) return; source = next; pending = undefined; const script = element('script'); script.textContent = `${next}\\n//# sourceURL=dsh-mobile-custom.js`; document.head.append(script); script.remove(); const mount = registeredMount(); if (mount === undefined) return; const nextRoot = element('div'); nextRoot.dataset.dshMobileExtension = 'true'; document.body.append(nextRoot); const nextDispose = mount({ document, request: mobileRequest, root: nextRoot, window }); disposeActive?.(); activeRoot?.remove(); activeRoot = nextRoot; disposeActive = typeof nextDispose === 'function' ? nextDispose : undefined } catch { /* Preserve the last good customization during reconnects. */ } }\n void refreshCss(); void refreshJs()\n const timer = window.setInterval(() => { void refreshCss(); void refreshJs() }, 1_000)\n return () => { clearInterval(timer); disposeActive?.(); activeRoot?.remove(); style.remove(); if (previous === undefined) delete window.dshMobile; else window.dshMobile = previous }\n}\n\nconst CONTROL_STYLES = `\n.dsh-mobile-control{position:fixed;z-index:1000;left:16px;bottom:64px;font:14px/1.45 system-ui;color:var(--dsw-alias-label-primary,#16181d)}\n.dsh-mobile-control__panel{box-sizing:border-box;width:min(328px,calc(100vw - 32px));padding:16px;border:1px solid var(--dsw-alias-border-subtle,#e1e5eb);border-radius:18px;background:var(--dsw-alias-bg-layer-2,#fff);box-shadow:0 18px 50px rgb(15 23 42 / 18%)}\n.dsh-mobile-control__header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:10px}.dsh-mobile-control__panel h2{margin:0;font-size:17px;line-height:24px}.dsh-mobile-control__close{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;border:0;border-radius:10px;background:transparent;color:inherit;font-size:24px;line-height:1;cursor:pointer}.dsh-mobile-control__close:hover{background:var(--dsw-alias-interactive-bg-hover,#f1f3f6)}\n.dsh-mobile-control__access{display:flex;align-items:baseline;gap:6px;min-width:0;margin:0 0 12px}.dsh-mobile-control__access[hidden]{display:none}.dsh-mobile-control__access-label{flex:none;color:var(--dsw-alias-label-secondary,#606873);white-space:nowrap}.dsh-mobile-control__access-label::after{content:\":\"}.dsh-mobile-control__access-link{min-width:0;overflow:hidden;color:#2563eb;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.dsh-mobile-control__access-link:hover{text-decoration:underline}\n.dsh-mobile-control__status{margin:0 0 14px;overflow-wrap:anywhere;color:var(--dsw-alias-label-secondary,#606873)}.dsh-mobile-control__status::before{display:inline-block;width:8px;height:8px;margin-right:7px;border-radius:50%;background:#98a1ad;content:\"\"}.dsh-mobile-control__status.is-running::before{background:#16a36a}.dsh-mobile-control__status.is-key{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:12px;word-break:break-all}\n.dsh-mobile-control__actions{display:flex;flex-wrap:wrap;gap:8px}.dsh-mobile-control__actions button{min-height:40px;padding:8px 12px;border-radius:11px;font:inherit;cursor:pointer}.dsh-mobile-control__secondary{border:1px solid var(--dsw-alias-border-normal,#cfd5dd);background:transparent;color:inherit}.dsh-mobile-control__primary{border:1px solid #2563eb;background:#2563eb;color:#fff}.dsh-mobile-control__actions button:disabled{cursor:not-allowed;opacity:.45}\n.dsh-mobile-control__trigger{box-sizing:border-box;display:flex;align-items:center;gap:8px;width:calc(100% + 8px);height:34px;margin:4px -4px;padding:6px 2px 6px 10px;border:0;border-radius:12px;background:transparent;color:var(--dsw-alias-label-primary,#16181d);font:14px/22px system-ui;cursor:pointer}.dsh-mobile-control__trigger:hover{background:var(--dsw-alias-interactive-bg-hover,#f1f3f6)}.dsh-mobile-control__trigger.is-rail{width:36px;height:36px;margin:8px 0 10px;padding:0;justify-content:center;border-radius:50%}.dsh-mobile-control__trigger-icon{position:relative;box-sizing:border-box;flex:none;width:14px;height:19px;border:1.7px solid currentColor;border-radius:3px}.dsh-mobile-control__trigger-icon::after{position:absolute;right:4px;bottom:2px;width:4px;height:1.5px;border-radius:2px;background:currentColor;content:\"\"}.dsh-mobile-control__trigger-label{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}\n`\n\n/** Mount the desktop control or mobile feature enhancements. */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => {\n const loopback = isLoopbackHost(location.hostname) && !new URLSearchParams(location.search).has('dsh-mobile-preview')\n const style = element('style'); style.dataset.plugin = 'dsh-mobile'; style.textContent = loopback\n ? CONTROL_STYLES\n : NATIVE_MOBILE_STYLES\n document.head.append(style)\n if (!loopback) {\n const removeCustom = installCustomAssets()\n const removeSurface = installNativeMobileSurface()\n return () => { removeCustom(); removeSurface(); style.remove() }\n }\n const control = installControl()\n const disposeSlot = ctx.slots.inject('sidebar.footer.action', () => ctx.slots.register({ name: 'sidebar.footer.action', id: 'dsh-mobile' }, ({ wide }) => createElement('button', {\n 'aria-expanded': false,\n 'aria-label': '移动访问',\n className: `dsh-mobile-control__trigger${wide ? '' : ' is-rail'}`,\n type: 'button',\n title: '移动访问',\n onClick: control.toggle,\n }, createElement('span', { 'aria-hidden': true, className: 'dsh-mobile-control__trigger-icon' }), wide ? createElement('span', { className: 'dsh-mobile-control__trigger-label' }, '移动访问') : undefined)))\n return () => { disposeSlot(); control.remove(); style.remove() }\n }, 'dsh-mobile: stock mobile adaptation and local control')\n}\n\n/** Client services required by the mobile adaptation. */\nexport const inject: readonly string[] = ['slots']\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-mobile",
3
- "version": "0.1.0-alpha.20",
3
+ "version": "0.1.0-alpha.22",
4
4
  "private": false,
5
5
  "description": "DeepSeek Harness 移动端适配与安全局域网访问插件,支持 Android App 和手机浏览器。",
6
6
  "type": "module",