dsh-mobile 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -39,6 +39,7 @@ window.__ModuleLoader__.load({
39
39
  clearAllDevices: "Clear all devices",
40
40
  pairingQr: "Pairing QR code",
41
41
  remoteIntro: "Choose the remote channel that suits you. Switching or disabling remote access does not affect the local network.",
42
+ httpFrameWarning: "HTTP pages may be embedded for compatibility, but their contents are unencrypted and can be altered. Use HTTPS for sensitive work.",
42
43
  chooseProvider: "Choose connection method",
43
44
  currentProvider: "Current connection",
44
45
  remoteStateOff: "Off",
@@ -207,6 +208,7 @@ window.__ModuleLoader__.load({
207
208
  clearAllDevices: "Rimuovi tutti i dispositivi",
208
209
  pairingQr: "Codice QR di abbinamento",
209
210
  remoteIntro: "Scegli il canale remoto più adatto. Cambiare o disattivare l’accesso remoto non influisce sulla rete locale.",
211
+ httpFrameWarning: "Le pagine HTTP possono essere incorporate per compatibilità, ma i contenuti non sono cifrati e possono essere alterati. Usa HTTPS per le attività sensibili.",
210
212
  chooseProvider: "Scegli metodo di connessione",
211
213
  currentProvider: "Connessione attuale",
212
214
  remoteStateOff: "Disattivata",
@@ -377,6 +379,7 @@ window.__ModuleLoader__.load({
377
379
  clearAllDevices: "清除所有设备",
378
380
  pairingQr: "配对二维码",
379
381
  remoteIntro: "选择更适合你的远程通道。切换或关闭远程访问不会影响局域网。",
382
+ httpFrameWarning: "为兼容性允许嵌入 HTTP 页面,但内容未加密,可能被篡改;处理敏感内容请使用 HTTPS。",
380
383
  chooseProvider: "选择连接方式",
381
384
  currentProvider: "当前连接",
382
385
  remoteStateOff: "未启用",
@@ -2327,6 +2330,55 @@ window.__ModuleLoader__.load({
2327
2330
  };
2328
2331
  }
2329
2332
  //#endregion
2333
+ //#region src/local-admin-host.ts
2334
+ /** Browser-safe desktop-admin Host checks. Do not import Node APIs here. */
2335
+ function unwrapBrackets(hostname) {
2336
+ return hostname.startsWith("[") && hostname.endsWith("]") ? hostname.slice(1, -1) : hostname;
2337
+ }
2338
+ function parseIpv4(hostname) {
2339
+ const parts = hostname.split(".");
2340
+ if (parts.length !== 4) return void 0;
2341
+ const octets = [];
2342
+ for (const part of parts) {
2343
+ if (!/^(?:0|[1-9]\d{0,2})$/u.test(part)) return void 0;
2344
+ const value = Number(part);
2345
+ if (value > 255) return void 0;
2346
+ octets.push(value);
2347
+ }
2348
+ return octets;
2349
+ }
2350
+ function isLoopbackIpv4(octets) {
2351
+ return octets[0] === 127;
2352
+ }
2353
+ function isPrivateIpv4(octets) {
2354
+ return octets[0] === 10 || octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31 || octets[0] === 192 && octets[1] === 168;
2355
+ }
2356
+ function isLinkLocalIpv4(octets) {
2357
+ return octets[0] === 169 && octets[1] === 254;
2358
+ }
2359
+ /**
2360
+ * Hostnames that may appear on the DSH desktop admin surface.
2361
+ * Loopback, RFC1918, and IPv4 link-local are accepted. Public IPs,
2362
+ * CGNAT, and arbitrary DNS names stay rejected so DNS rebinding
2363
+ * cannot reach `/api/mobile-access`.
2364
+ */
2365
+ function isLocalAdminHostname(hostname) {
2366
+ const host = unwrapBrackets(hostname).trim().toLowerCase();
2367
+ if (host === "localhost" || host === "::1") return true;
2368
+ const octets = parseIpv4(host);
2369
+ if (octets === void 0) return false;
2370
+ return isLoopbackIpv4(octets) || isPrivateIpv4(octets) || isLinkLocalIpv4(octets);
2371
+ }
2372
+ /**
2373
+ * Whether the current browser document should mount the desktop Mobile access
2374
+ * control. Dedicated Mobile HTTPS (the phone surface) stays native even when
2375
+ * the Host is a private LAN address.
2376
+ */
2377
+ function isDesktopAdminSurface(hostname, search = "", frontend) {
2378
+ const query = search.startsWith("?") ? search.slice(1) : search;
2379
+ return isLocalAdminHostname(hostname) && frontend !== "dedicated" && !new URLSearchParams(query).has("dsh-mobile-preview");
2380
+ }
2381
+ //#endregion
2330
2382
  //#region src/client.ts
2331
2383
  const queuedDefinitions = [];
2332
2384
  let queuedLegacyMount;
@@ -2338,9 +2390,6 @@ window.__ModuleLoader__.load({
2338
2390
  queuedDefinitions.push(definition);
2339
2391
  }
2340
2392
  };
2341
- function isLoopbackHost(hostname) {
2342
- return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]";
2343
- }
2344
2393
  function selectMobileControlLocale(documentLanguage = "", navigatorLanguages = []) {
2345
2394
  for (const value of [documentLanguage, ...navigatorLanguages]) {
2346
2395
  const language = value.trim().toLowerCase().split(/[-_]/u)[0];
@@ -2728,6 +2777,10 @@ window.__ModuleLoader__.load({
2728
2777
  remoteView.hidden = true;
2729
2778
  const remoteIntro = element("p", "dsh-mobile-control__intro");
2730
2779
  remoteIntro.textContent = t("remoteIntro");
2780
+ const httpFrameWarning = element("p", "dsh-mobile-control__http-frame-warning");
2781
+ httpFrameWarning.textContent = t("httpFrameWarning");
2782
+ httpFrameWarning.hidden = location.protocol !== "https:";
2783
+ httpFrameWarning.setAttribute("role", "note");
2731
2784
  const providerSection = element("section", "dsh-mobile-control__provider-section");
2732
2785
  const providerHeading = element("h3", "dsh-mobile-control__section-title");
2733
2786
  providerHeading.textContent = t("chooseProvider");
@@ -3372,7 +3425,7 @@ window.__ModuleLoader__.load({
3372
3425
  header.append(title, headerActions);
3373
3426
  actions.append(toggle, pair, linkPair);
3374
3427
  lanView.append(lanSetup, access, qrBox, status, extensionStatus, actions, manageRow, devicePanel);
3375
- remoteView.append(remoteIntro, providerSection, remoteWorkspace);
3428
+ remoteView.append(remoteIntro, httpFrameWarning, providerSection, remoteWorkspace);
3376
3429
  diagnosticsView.append(diagnosticsIntro, diagnosticsSummary, diagnosticsToolbar, diagnosticsFeedback, diagnosticsChecks, wsPathsSection, diagnosticsDetails);
3377
3430
  panel.append(header, releaseNotice, updateCard, appDownload, switcher, lanView, remoteView, diagnosticsView);
3378
3431
  root.append(panel);
@@ -4918,6 +4971,15 @@ window.__ModuleLoader__.load({
4918
4971
  if (generation !== void 0) result.set("x-dsh-mobile-extension-generation", generation);
4919
4972
  return result;
4920
4973
  }
4974
+ /** Build the JSON request used by a mobile extension to invoke a Host action. */
4975
+ function extensionActionRequestInit(generation, input, signal) {
4976
+ return {
4977
+ method: "POST",
4978
+ headers: extensionGenerationHeaders(generation, { "content-type": "application/json" }),
4979
+ body: JSON.stringify(input ?? {}),
4980
+ signal
4981
+ };
4982
+ }
4921
4983
  function registerUniqueDisposable(entries, claimedIds, id, mount) {
4922
4984
  if (claimedIds.has(id)) throw new Error(`duplicate lifecycle id: ${id}`);
4923
4985
  claimedIds.add(id);
@@ -5482,12 +5544,7 @@ window.__ModuleLoader__.load({
5482
5544
  host: {
5483
5545
  invoke: (action, input) => {
5484
5546
  ensureCurrent();
5485
- return mobileRequest(`/mobile-access/extensions/${encodeURIComponent(id)}/actions/${encodeURIComponent(action)}`, {
5486
- method: "POST",
5487
- headers: extensionGenerationHeaders(hostGeneration),
5488
- body: JSON.stringify(input ?? {}),
5489
- signal: controller.signal
5490
- }).then(async (response) => {
5547
+ return mobileRequest(`/mobile-access/extensions/${encodeURIComponent(id)}/actions/${encodeURIComponent(action)}`, extensionActionRequestInit(hostGeneration, input, controller.signal)).then(async (response) => {
5491
5548
  const value = await response.json();
5492
5549
  if (!response.ok) throw new Error(typeof value === "object" && value !== null && "error" in value ? String(value.error) : `HTTP ${String(response.status)}`);
5493
5550
  return value;
@@ -5953,7 +6010,7 @@ window.__ModuleLoader__.load({
5953
6010
  .dsh-mobile-control__panel{box-sizing:border-box;width:min(380px,calc(100vw - 32px));max-height:calc(100vh - 140px);overflow-y:auto;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%)}
5954
6011
  .dsh-mobile-control__header{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:10px}.dsh-mobile-control__panel h2{margin:0;font-size:17px;line-height:24px}.dsh-mobile-control__header-actions{display:flex;align-items:center;gap:2px}.dsh-mobile-control__update-plugin,.dsh-mobile-control__diagnostic-entry,.dsh-mobile-control__close{display:inline-flex;align-items:center;justify-content:center;min-width:44px;height:44px;padding:0;border:0;border-radius:10px;background:transparent;color:inherit;cursor:pointer}.dsh-mobile-control__update-plugin,.dsh-mobile-control__diagnostic-entry{padding:0 8px;color:#2563eb;font:650 12px/1 system-ui;white-space:nowrap}.dsh-mobile-control__update-plugin[hidden]{display:none}.dsh-mobile-control__update-plugin:disabled{cursor:wait;opacity:.55}.dsh-mobile-control__close{font-size:24px;line-height:1}.dsh-mobile-control__update-plugin:hover:not(:disabled),.dsh-mobile-control__diagnostic-entry:hover,.dsh-mobile-control__close:hover{background:var(--dsw-alias-interactive-bg-hover,#f1f3f6)}
5955
6012
  .dsh-mobile-control__release-notice{margin:-2px 0 10px;padding:8px 10px;border-radius:9px;background:var(--dsw-alias-bg-layer-1,#eff6ff);color:var(--dsw-alias-label-primary,#1d4ed8);font-size:11px;line-height:1.45}.dsh-mobile-control__release-notice.is-error{color:#dc2626}.dsh-mobile-control__release-notice[hidden]{display:none}.dsh-mobile-control__update-card{margin:0 0 10px;padding:11px;border:1px solid var(--dsw-alias-border-subtle,#dbe1e8);border-radius:12px;background:var(--dsw-alias-bg-layer-1,#f8fafc)}.dsh-mobile-control__update-card[hidden]{display:none}.dsh-mobile-control__update-card-title{margin:0 0 7px;color:var(--dsw-alias-label-primary,#16181d);font:650 13px/1.4 system-ui}.dsh-mobile-control__update-notes{display:block;box-sizing:border-box;max-height:150px;overflow-y:auto;margin:0 0 8px;padding:8px 10px;border:1px solid var(--dsw-alias-border-subtle,#e1e5eb);border-radius:9px;background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-secondary,#475569);white-space:pre-wrap;word-break:break-word;font:11px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.dsh-mobile-control__update-notes[hidden]{display:none}.dsh-mobile-control__update-notice{margin:0 0 9px;padding:7px 9px;border-radius:8px;background:#fff4d6;color:#92400e;font-size:11px;line-height:1.5}.dsh-mobile-control__update-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px}.dsh-mobile-control__update-actions .dsh-mobile-control__primary,.dsh-mobile-control__update-actions .dsh-mobile-control__secondary{min-height:34px;padding:0 12px}.dsh-mobile-control__app-download{display:flex;align-items:center;justify-content:space-between;box-sizing:border-box;min-height:38px;margin:0 0 10px;padding:8px 11px;border:1px solid var(--dsw-alias-border-subtle,#dbe1e8);border-radius:11px;background:var(--dsw-alias-bg-layer-1,#f7f8fa);color:var(--dsw-alias-label-primary,#16181d);font:600 12px/1.3 system-ui;text-decoration:none}.dsh-mobile-control__app-download[hidden]{display:none}.dsh-mobile-control__app-download::after{color:#2563eb;font-size:14px;content:"↗"}.dsh-mobile-control__app-download:hover{border-color:#9fb9e8;background:var(--dsw-alias-interactive-bg-hover-solid,var(--dsw-alias-bg-layer-2,#f5f8ff));color:var(--dsw-alias-label-primary,#1d4ed8)}
5956
- .dsh-mobile-control__switcher{display:grid;grid-template-columns:repeat(2,1fr);gap:4px;margin:0 0 14px;padding:4px;border-radius:12px;background:var(--dsw-alias-bg-layer-1,#f3f5f8)}.dsh-mobile-control__switcher[hidden]{display:none}.dsh-mobile-control__tab{min-height:36px;border:0;border-radius:9px;background:transparent;color:var(--dsw-alias-label-secondary,#606873);font:600 13px/1 system-ui;cursor:pointer}.dsh-mobile-control__tab.is-active{background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#16181d);box-shadow:0 1px 3px rgb(15 23 42 / 10%)}.dsh-mobile-control__view[hidden]{display:none}.dsh-mobile-control__intro{margin:0 0 12px;color:var(--dsw-alias-label-secondary,#606873);font-size:12px;line-height:1.55}.dsh-mobile-control__view.is-remote .dsh-mobile-control__actions{display:grid;grid-template-columns:1fr 1fr;gap:8px}.dsh-mobile-control__view.is-remote .dsh-mobile-control__actions button[hidden]{display:none}
6013
+ .dsh-mobile-control__switcher{display:grid;grid-template-columns:repeat(2,1fr);gap:4px;margin:0 0 14px;padding:4px;border-radius:12px;background:var(--dsw-alias-bg-layer-1,#f3f5f8)}.dsh-mobile-control__switcher[hidden]{display:none}.dsh-mobile-control__tab{min-height:36px;border:0;border-radius:9px;background:transparent;color:var(--dsw-alias-label-secondary,#606873);font:600 13px/1 system-ui;cursor:pointer}.dsh-mobile-control__tab.is-active{background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#16181d);box-shadow:0 1px 3px rgb(15 23 42 / 10%)}.dsh-mobile-control__view[hidden]{display:none}.dsh-mobile-control__intro{margin:0 0 12px;color:var(--dsw-alias-label-secondary,#606873);font-size:12px;line-height:1.55}.dsh-mobile-control__http-frame-warning{box-sizing:border-box;margin:-4px 0 12px;padding:8px 10px;border:1px solid #d6a83f;border-radius:9px;background:var(--dsw-alias-bg-layer-1,#fff7df);color:var(--dsw-alias-label-primary,#694b00);font-size:11px;line-height:1.5;overflow-wrap:anywhere}.dsh-mobile-control__http-frame-warning[hidden]{display:none}.dsh-mobile-control__view.is-remote .dsh-mobile-control__actions{display:grid;grid-template-columns:1fr 1fr;gap:8px}.dsh-mobile-control__view.is-remote .dsh-mobile-control__actions button[hidden]{display:none}
5957
6014
  .dsh-mobile-control__provider-section{position:relative;margin:0 0 14px}.dsh-mobile-control__section-title{margin:0 0 8px;color:var(--dsw-alias-label-primary,#16181d);font:650 13px/1.4 system-ui}.dsh-mobile-control__provider-section>.dsh-mobile-control__section-title{padding-right:42px}.dsh-mobile-control__provider-choices{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.dsh-mobile-control__provider{display:flex;min-width:0;flex-direction:column;gap:6px;min-height:94px;padding:10px 11px;border:1px solid var(--dsw-alias-border-subtle,#dbe1e8);border-radius:13px;background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#16181d);text-align:left;cursor:pointer;touch-action:manipulation;transition:border-color 160ms ease,background-color 160ms ease,box-shadow 160ms ease}.dsh-mobile-control__provider:hover{border-color:#6f96db;background:var(--dsw-alias-interactive-bg-hover-solid,var(--dsw-alias-bg-layer-1,#f8fbff))}.dsh-mobile-control__provider.is-selected{border-color:#2563eb;background:var(--dsw-alias-interactive-bg-active,var(--dsw-alias-bg-layer-1,#f5f8ff));box-shadow:0 0 0 1px #2563eb inset}.dsh-mobile-control__provider:disabled{cursor:wait;opacity:.62}.dsh-mobile-control__provider-top{display:flex;min-width:0;align-items:flex-start;justify-content:space-between;gap:5px}.dsh-mobile-control__provider-top strong{min-width:0;font-size:12px;line-height:1.3}.dsh-mobile-control__provider-badge{flex:none;padding:2px 5px;border-radius:999px;background:#e8f0ff;color:#1d4ed8;font:650 9px/1.25 system-ui}.dsh-mobile-control__provider-badge.is-cpolar{background:#eaf8f2;color:#087454}.dsh-mobile-control__provider-description{color:var(--dsw-alias-label-secondary,#606873);font-size:10px;line-height:1.45}.dsh-mobile-control__provider-info{position:absolute;z-index:5;top:-13px;right:-8px}.dsh-mobile-control__provider-info-button{display:flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--dsw-alias-label-secondary,#475569);cursor:pointer;touch-action:manipulation}.dsh-mobile-control__provider-info-button:hover{background:var(--dsw-alias-interactive-bg-hover,#f1f5f9);color:#2563eb}.dsh-mobile-control__provider-info-glyph{display:flex;align-items:center;justify-content:center;box-sizing:border-box;width:18px;height:18px;border:1.5px solid currentColor;border-radius:50%;font:700 12px/1 system-ui}.dsh-mobile-control__provider-info-popover{position:absolute;z-index:6;top:38px;right:4px;box-sizing:border-box;width:min(292px,calc(100vw - 72px));padding:10px 12px;border:1px solid var(--dsw-alias-border-subtle,#dbe1e8);border-radius:12px;background:var(--dsw-alias-bg-layer-2,#fff);box-shadow:0 10px 28px rgb(15 23 42 / 16%)}.dsh-mobile-control__provider-info-popover[hidden]{display:none}.dsh-mobile-control__provider-info-popover strong,.dsh-mobile-control__provider-info-popover span{display:block}.dsh-mobile-control__provider-info-popover strong{margin-bottom:3px;font-size:12px}.dsh-mobile-control__provider-info-popover span{color:var(--dsw-alias-label-secondary,#606873);font-size:11px;line-height:1.55}
5958
6015
  .dsh-mobile-control__self-hosted{margin:8px 0 0;border:1px solid var(--dsw-alias-border-subtle,#dbe1e8);border-radius:12px;background:var(--dsw-alias-bg-layer-1,#f8fafc)}.dsh-mobile-control__self-hosted-summary{display:flex;box-sizing:border-box;min-height:48px;align-items:center;justify-content:space-between;gap:10px;padding:8px 11px;cursor:pointer;list-style-position:inside}.dsh-mobile-control__self-hosted-summary>span:first-child{display:flex;min-width:0;flex-direction:column;gap:1px}.dsh-mobile-control__self-hosted-summary strong{font-size:11px}.dsh-mobile-control__self-hosted-summary span span{color:var(--dsw-alias-label-secondary,#606873);font-size:9px;line-height:1.35}.dsh-mobile-control__provider-badge.is-frp{background:#eef0f3;color:#475569}.dsh-mobile-control__self-hosted-body{padding:0 8px 8px}.dsh-mobile-control__provider.is-frp{width:100%;min-height:64px;background:var(--dsw-alias-bg-layer-2,#fff)}
5959
6016
  .dsh-mobile-control__cpolar-setup{margin:0 0 12px;padding:12px;border:1px solid var(--dsw-alias-border-subtle,#dbe1e8);border-radius:13px;background:var(--dsw-alias-bg-layer-2,#fff)}.dsh-mobile-control__cpolar-setup[hidden],.dsh-mobile-control__cpolar-account[hidden],.dsh-mobile-control__details[hidden],.dsh-mobile-control__view.is-remote .dsh-mobile-control__actions[hidden],.dsh-mobile-control__danger[hidden]{display:none}.dsh-mobile-control__component-status,.dsh-mobile-control__component-note{margin:0 0 10px;color:var(--dsw-alias-label-secondary,#606873);font-size:11px;line-height:1.55}.dsh-mobile-control__cpolar-setup>.dsh-mobile-control__primary{width:100%;min-height:44px;padding:9px 12px;border-radius:10px;font:600 12px/1.3 system-ui;cursor:pointer}.dsh-mobile-control__cpolar-account{margin-top:10px}.dsh-mobile-control__link-row{display:flex;flex-wrap:wrap;gap:6px 12px;margin:0 0 10px}.dsh-mobile-control__text-link{color:#2563eb;font-size:11px;text-decoration:none}.dsh-mobile-control__text-link:hover{text-decoration:underline}.dsh-mobile-control__token-label{display:flex;flex-direction:column;gap:5px;margin:0 0 8px;color:var(--dsw-alias-label-secondary,#606873);font-size:11px}.dsh-mobile-control__token{box-sizing:border-box;width:100%;min-height:44px;padding:9px 10px;border:1px solid var(--dsw-alias-border-normal,#cfd5dd);border-radius:10px;background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-bg-layer-2,#fff));color:var(--dsw-alias-label-primary,#16181d);font:16px/1.4 system-ui}.dsh-mobile-control__cpolar-connect{display:flex;align-items:center;justify-content:center;box-sizing:border-box;width:100%;min-height:44px;padding:10px 14px;border-radius:12px;font:650 13px/1.2 system-ui;cursor:pointer;transition:background-color 160ms ease,border-color 160ms ease,opacity 160ms ease}.dsh-mobile-control__cpolar-connect:hover:not(:disabled){border-color:#1d4ed8;background:#1d4ed8}.dsh-mobile-control__cpolar-connect:active:not(:disabled){border-color:#1e40af;background:#1e40af}.dsh-mobile-control__cpolar-connect:disabled{cursor:wait;opacity:.55}.dsh-mobile-control__details{margin:10px 0 0;border-top:1px solid var(--dsw-alias-border-subtle,#e1e5eb);padding-top:9px}.dsh-mobile-control__details>summary{min-height:30px;color:var(--dsw-alias-label-secondary,#606873);font-size:11px;line-height:30px;cursor:pointer}.dsh-mobile-control__details-body{display:flex;flex-wrap:wrap;align-items:center;gap:7px 12px;padding:4px 0}.dsh-mobile-control__details-body p{flex:1 0 100%;margin:0;color:var(--dsw-alias-label-secondary,#606873);font-size:11px;line-height:1.5}.dsh-mobile-control__storage{display:block;flex:1 0 100%;max-width:100%;overflow:hidden;padding:7px 8px;border-radius:8px;background:var(--dsw-alias-bg-layer-1,#f3f5f8);color:var(--dsw-alias-label-secondary,#475569);font:10px/1.4 ui-monospace,SFMono-Regular,Consolas,monospace;text-overflow:ellipsis;white-space:nowrap}.dsh-mobile-control__danger{flex:1 0 100%;min-height:38px;margin-top:3px;padding:7px 10px;border:1px solid #dc2626;border-radius:9px;background:transparent;color:#dc2626;font:12px/1.3 system-ui;cursor:pointer}
@@ -5983,12 +6040,12 @@ window.__ModuleLoader__.load({
5983
6040
  return trustAuthenticatedGatewayConnection(ctx.get("connection"));
5984
6041
  }, "dsh-mobile: authenticated gateway client trust");
5985
6042
  ctx.effect(() => {
5986
- const loopback = isLoopbackHost(location.hostname) && !new URLSearchParams(location.search).has("dsh-mobile-preview");
6043
+ const desktopAdmin = isDesktopAdminSurface(location.hostname, location.search, window.__DSH_MOBILE_FRONTEND__);
5987
6044
  const style = element("style");
5988
6045
  style.dataset.plugin = "dsh-mobile";
5989
- style.textContent = loopback ? CONTROL_STYLES : NATIVE_MOBILE_STYLES;
6046
+ style.textContent = desktopAdmin ? CONTROL_STYLES : NATIVE_MOBILE_STYLES;
5990
6047
  document.head.append(style);
5991
- if (!loopback) {
6048
+ if (!desktopAdmin) {
5992
6049
  const removeSettingsAction = ctx.slots.inject("settings.general.item", () => ctx.slots.register({
5993
6050
  name: "settings.general.item",
5994
6051
  id: "dsh-mobile-switch-computer",
@@ -6066,6 +6123,7 @@ window.__ModuleLoader__.load({
6066
6123
  exports.diagnosticEntriesForRender = diagnosticEntriesForRender;
6067
6124
  exports.diagnosticOverallForChecks = diagnosticOverallForChecks;
6068
6125
  exports.diagnosticServerCopy = diagnosticServerCopy;
6126
+ exports.extensionActionRequestInit = extensionActionRequestInit;
6069
6127
  exports.extensionAssetUrl = extensionAssetUrl;
6070
6128
  exports.extensionGenerationHeaders = extensionGenerationHeaders;
6071
6129
  exports.extensionRouteUrl = extensionRouteUrl;