ds-harness-remote 0.3.30 → 0.3.32

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/dist/client.js CHANGED
@@ -1626,11 +1626,19 @@ Minimum version required to store current data is: ` + bestVersion + `.
1626
1626
  function shouldUseRemoteFileViewer(status) {
1627
1627
  return status.mode === "remote" && status.remoteFeatures?.fileViewer === !0;
1628
1628
  }
1629
- function createRemoteFileContentProvider(call) {
1629
+ var REMOTE_FILE_SAVE_AS_MAX_BYTES = 100 * 1024 * 1024;
1630
+ function shouldAllowRemoteFileSaveAs(status) {
1631
+ return shouldUseRemoteFileViewer(status) && (status.transport === "LAN" || status.transport === "P2P" || status.transport === "TURN");
1632
+ }
1633
+ function createRemoteFileContentProvider(call, options = {}) {
1630
1634
  return {
1631
1635
  id: "dsh-remote-files",
1632
1636
  priority: 1e4,
1633
1637
  supports: () => !0,
1638
+ saveAsAllowed: () => ({
1639
+ allowed: currentSaveAsAllowed(options.saveAsAllowed),
1640
+ maxBytes: options.saveAsMaxBytes ?? REMOTE_FILE_SAVE_AS_MAX_BYTES
1641
+ }),
1634
1642
  async stat(locator, signal) {
1635
1643
  let value = await call("fileviewer.stat", { path: locator }, signal);
1636
1644
  if (value.exists)
@@ -1670,6 +1678,9 @@ Minimum version required to store current data is: ` + bestVersion + `.
1670
1678
  }
1671
1679
  };
1672
1680
  }
1681
+ function currentSaveAsAllowed(value) {
1682
+ return typeof value == "function" ? value() : value === !0;
1683
+ }
1673
1684
  function decodeBase64(value) {
1674
1685
  let binary = atob(value), bytes = new Uint8Array(binary.length);
1675
1686
  for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
@@ -1729,6 +1740,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
1729
1740
  local: "Local",
1730
1741
  remoteTarget: "Remote \xB7 {name}",
1731
1742
  thisMachineLocal: "This machine (Local)",
1743
+ currentDevice: "Current device",
1732
1744
  noRemoteHosts: "No authorized remote Host for this account.",
1733
1745
  online: "Online",
1734
1746
  offline: "Offline",
@@ -1777,6 +1789,15 @@ Minimum version required to store current data is: ` + bestVersion + `.
1777
1789
  remoteProgressAuthorizingPeerDetail: "Confirming account membership and pinned Host identity.",
1778
1790
  remoteProgressOpeningChannel: "Opening encrypted channel",
1779
1791
  remoteProgressOpeningChannelDetail: "Trying LAN, P2P, TURN, then Relay if needed.",
1792
+ remoteProgressProbeLan: "Probing LAN",
1793
+ remoteProgressProbeLanDetail: "Checking whether the Host is reachable on the local network.",
1794
+ remoteProgressProbeP2p: "Probing P2P",
1795
+ remoteProgressProbeP2pDetail: "Checking direct internet candidates between this device and the Host.",
1796
+ remoteProgressProbeTurn: "Probing TURN",
1797
+ remoteProgressProbeTurnDetail: "Checking the TURN relay path for restricted networks.",
1798
+ remoteProgressProbeRelay: "Preparing Relay",
1799
+ remoteProgressProbeRelayDetail: "Preparing the encrypted Server Relay fallback if direct paths do not open.",
1800
+ remoteProgressTryingPrefix: "Trying ",
1780
1801
  remoteProgressLoadingWorkspaces: "Loading workspaces",
1781
1802
  remoteProgressLoadingWorkspacesDetail: "Reading the remote Harness workspace list through the tunnel.",
1782
1803
  remoteProgressOpeningWorkspace: "Opening workspace",
@@ -1913,6 +1934,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
1913
1934
  local: "\u672C\u5730",
1914
1935
  remoteTarget: "\u8FDC\u7A0B \xB7 {name}",
1915
1936
  thisMachineLocal: "\u6B64\u8BBE\u5907\uFF08\u672C\u5730\uFF09",
1937
+ currentDevice: "\u5F53\u524D\u8BBE\u5907",
1916
1938
  noRemoteHosts: "\u6B64\u8D26\u53F7\u6CA1\u6709\u5DF2\u6388\u6743\u7684\u8FDC\u7A0B Host\u3002",
1917
1939
  online: "\u5728\u7EBF",
1918
1940
  offline: "\u79BB\u7EBF",
@@ -1961,6 +1983,15 @@ Minimum version required to store current data is: ` + bestVersion + `.
1961
1983
  remoteProgressAuthorizingPeerDetail: "\u6B63\u5728\u786E\u8BA4\u8D26\u53F7\u6210\u5458\u5173\u7CFB\u548C\u5DF2\u56FA\u5B9A\u7684 Host \u8EAB\u4EFD\u3002",
1962
1984
  remoteProgressOpeningChannel: "\u6B63\u5728\u5EFA\u7ACB\u52A0\u5BC6\u901A\u9053",
1963
1985
  remoteProgressOpeningChannelDetail: "\u4F9D\u6B21\u5C1D\u8BD5\u5C40\u57DF\u7F51\u3001P2P\u3001TURN\uFF0C\u5FC5\u8981\u65F6\u56DE\u843D\u5230 Relay\u3002",
1986
+ remoteProgressProbeLan: "\u6B63\u5728\u63A2\u6D4B\u5C40\u57DF\u7F51",
1987
+ remoteProgressProbeLanDetail: "\u68C0\u67E5\u5F53\u524D\u8BBE\u5907\u662F\u5426\u80FD\u901A\u8FC7\u672C\u5730\u7F51\u7EDC\u76F4\u8FDE Host\u3002",
1988
+ remoteProgressProbeP2p: "\u6B63\u5728\u63A2\u6D4B P2P",
1989
+ remoteProgressProbeP2pDetail: "\u68C0\u67E5\u5F53\u524D\u8BBE\u5907\u548C Host \u4E4B\u95F4\u7684\u4E92\u8054\u7F51\u76F4\u8FDE\u5019\u9009\u8DEF\u5F84\u3002",
1990
+ remoteProgressProbeTurn: "\u6B63\u5728\u63A2\u6D4B TURN",
1991
+ remoteProgressProbeTurnDetail: "\u68C0\u67E5\u53D7\u9650\u7F51\u7EDC\u4E0B\u53EF\u7528\u7684 TURN \u4E2D\u7EE7\u8DEF\u5F84\u3002",
1992
+ remoteProgressProbeRelay: "\u6B63\u5728\u51C6\u5907 Relay",
1993
+ remoteProgressProbeRelayDetail: "\u5982\u679C\u76F4\u8FDE\u8DEF\u5F84\u672A\u6253\u5F00\uFF0C\u5C06\u56DE\u843D\u5230\u52A0\u5BC6\u7684 Server Relay\u3002",
1994
+ remoteProgressTryingPrefix: "\u6B63\u5728\u5C1D\u8BD5 ",
1964
1995
  remoteProgressLoadingWorkspaces: "\u6B63\u5728\u52A0\u8F7D\u5DE5\u4F5C\u533A",
1965
1996
  remoteProgressLoadingWorkspacesDetail: "\u901A\u8FC7\u96A7\u9053\u8BFB\u53D6\u8FDC\u7AEF Harness \u5DE5\u4F5C\u533A\u5217\u8868\u3002",
1966
1997
  remoteProgressOpeningWorkspace: "\u6B63\u5728\u6253\u5F00\u5DE5\u4F5C\u533A",
@@ -2048,7 +2079,10 @@ Minimum version required to store current data is: ` + bestVersion + `.
2048
2079
  accountPasswordLogin: "\u8D26\u53F7\u5BC6\u7801",
2049
2080
  qrLoginExpired: "\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5\u3002",
2050
2081
  refreshQrCode: "\u5237\u65B0\u4E8C\u7EF4\u7801"
2051
- };
2082
+ }, defaultPreferredTransports = ["lan", "p2p", "turn", "relay"];
2083
+ function normalizedPreferredTransports(value) {
2084
+ return value === void 0 || value.length === 0 ? [...defaultPreferredTransports] : [...value];
2085
+ }
2052
2086
  function formatLocalTime(value) {
2053
2087
  let date = new Date(value);
2054
2088
  return Number.isNaN(date.getTime()) ? "\u2014" : date.toLocaleString();
@@ -2069,6 +2103,30 @@ Minimum version required to store current data is: ` + bestVersion + `.
2069
2103
  function shortDeviceId(value) {
2070
2104
  return value.length <= 14 ? value : `${value.slice(0, 8)}\u2026${value.slice(-4)}`;
2071
2105
  }
2106
+ function transportLabel(value, t) {
2107
+ return t(value === "lan" ? "remoteNetworkLan" : value === "p2p" ? "remoteNetworkP2p" : value === "turn" ? "remoteNetworkTurn" : "remoteNetworkRelay");
2108
+ }
2109
+ function transportDiagnosticLabel(value) {
2110
+ return value === "lan" ? "LAN" : value === "p2p" ? "P2P" : value === "turn" ? "TURN" : "Relay";
2111
+ }
2112
+ function transportProgressCopy(value) {
2113
+ return value === "lan" ? { label: "remoteProgressProbeLan", detail: "remoteProgressProbeLanDetail" } : value === "p2p" ? { label: "remoteProgressProbeP2p", detail: "remoteProgressProbeP2pDetail" } : value === "turn" ? { label: "remoteProgressProbeTurn", detail: "remoteProgressProbeTurnDetail" } : { label: "remoteProgressProbeRelay", detail: "remoteProgressProbeRelayDetail" };
2114
+ }
2115
+ function connectHostProgressSteps(preferredTransports) {
2116
+ let transports = normalizedPreferredTransports(preferredTransports);
2117
+ return [
2118
+ { label: "remoteProgressCheckingHost", detail: "remoteProgressCheckingHostDetail", percent: 12 },
2119
+ { label: "remoteProgressAuthorizingPeer", detail: "remoteProgressAuthorizingPeerDetail", percent: 30, delayMs: 280 },
2120
+ ...transports.map((transport, index) => ({
2121
+ ...transportProgressCopy(transport),
2122
+ percent: Math.min(76, 42 + index * 10),
2123
+ delayMs: 680 + index * 360,
2124
+ transports,
2125
+ activeTransport: transport
2126
+ })),
2127
+ { label: "remoteProgressLoadingWorkspaces", detail: "remoteProgressLoadingWorkspacesDetail", percent: 84, delayMs: 1520, transports }
2128
+ ];
2129
+ }
2072
2130
  function connectionErrorMessage(code, t) {
2073
2131
  return t(code === "ACCOUNT_AUTH_REQUIRED" || code === "AUTH_INVALID" || code === "TOKEN_EXPIRED" ? "connectionAuthorizationExpired" : code === "DEVICE_REVOKED" ? "connectionDeviceRevoked" : code === "DEVICE_OWNERSHIP_REQUIRED" ? "connectionOwnershipRequired" : code === "RATE_LIMITED" ? "connectionRateLimited" : code === "UNSUPPORTED_VERSION" ? "connectionVersionMismatch" : code === "INVALID_MESSAGE" ? "connectionInvalidResponse" : code === "CONNECTION_FAILED" || code === "SERVER_NOT_CONFIGURED" ? "connectionReachability" : "connectionUnexpected");
2074
2132
  }
@@ -2085,7 +2143,19 @@ Minimum version required to store current data is: ` + bestVersion + `.
2085
2143
  function RemoteProgressView(props) {
2086
2144
  let progress = props.progress;
2087
2145
  if (progress === void 0) return null;
2088
- let percent = Math.max(0, Math.min(100, Math.round(progress.percent)));
2146
+ let percent = Math.max(0, Math.min(100, Math.round(progress.percent))), activeTransportIndex = progress.transports?.findIndex((transport) => transport === progress.activeTransport) ?? -1, detail = progress.transports !== void 0 && progress.activeTransport !== void 0 && activeTransportIndex > -1 ? React.createElement(
2147
+ "span",
2148
+ { className: "dshRemoteProgressRoute" },
2149
+ props.t("remoteProgressTryingPrefix"),
2150
+ progress.transports.map((transport, index) => React.createElement(
2151
+ React.Fragment,
2152
+ { key: `${transport}:${index}` },
2153
+ index === 0 ? null : React.createElement("span", { className: "dshRemoteProgressRouteArrow", "aria-hidden": !0 }, " -> "),
2154
+ React.createElement("span", {
2155
+ className: index === activeTransportIndex ? "isActive" : void 0
2156
+ }, transportDiagnosticLabel(transport))
2157
+ ))
2158
+ ) : props.t(progress.detail);
2089
2159
  return React.createElement(
2090
2160
  "div",
2091
2161
  {
@@ -2099,6 +2169,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
2099
2169
  React.createElement("strong", null, props.t(progress.label)),
2100
2170
  React.createElement("span", null, `${percent}%`)
2101
2171
  ),
2172
+ React.createElement("p", null, detail),
2102
2173
  React.createElement("div", {
2103
2174
  className: "dshRemoteProgressBar",
2104
2175
  role: "progressbar",
@@ -2106,8 +2177,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
2106
2177
  "aria-valuemax": 100,
2107
2178
  "aria-valuenow": percent,
2108
2179
  "aria-label": props.t(progress.label)
2109
- }, React.createElement("span", { style: { width: `${percent}%` } })),
2110
- React.createElement("p", null, props.t(progress.detail))
2180
+ }, React.createElement("span", { style: { width: `${percent}%` } }))
2111
2181
  );
2112
2182
  }
2113
2183
  async function runRemoteProgress(steps, setProgress, progressRun, action) {
@@ -2125,12 +2195,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
2125
2195
  timers.forEach((timer) => window.clearTimeout(timer)), progressRun.current === runId && setProgress(void 0);
2126
2196
  }
2127
2197
  }
2128
- let connectHostProgressSteps = [
2129
- { label: "remoteProgressCheckingHost", detail: "remoteProgressCheckingHostDetail", percent: 12 },
2130
- { label: "remoteProgressAuthorizingPeer", detail: "remoteProgressAuthorizingPeerDetail", percent: 32, delayMs: 280 },
2131
- { label: "remoteProgressOpeningChannel", detail: "remoteProgressOpeningChannelDetail", percent: 58, delayMs: 760 },
2132
- { label: "remoteProgressLoadingWorkspaces", detail: "remoteProgressLoadingWorkspacesDetail", percent: 82, delayMs: 1350 }
2133
- ], openWorkspaceProgressSteps = [
2198
+ let openWorkspaceProgressSteps = [
2134
2199
  { label: "remoteProgressOpeningWorkspace", detail: "remoteProgressOpeningWorkspaceDetail", percent: 30 },
2135
2200
  { label: "remoteProgressSwitchingWorkspace", detail: "remoteProgressSwitchingWorkspaceDetail", percent: 74, delayMs: 520 }
2136
2201
  ];
@@ -2428,7 +2493,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
2428
2493
  setBusy(!0), setError(void 0);
2429
2494
  try {
2430
2495
  setWorkspaces(await runRemoteProgress(
2431
- connectHostProgressSteps,
2496
+ connectHostProgressSteps(status?.preferredTransports),
2432
2497
  setProgress,
2433
2498
  progressRun,
2434
2499
  () => props.control("workspaces.list", { targetDeviceId: host.deviceId })
@@ -2521,7 +2586,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
2521
2586
  setError(messageOf(reason)), setBusy(!1);
2522
2587
  }
2523
2588
  }
2524
- }, remoteLabel = status?.mode === "remote" ? t("activeRemote", { name: status.target?.name ?? t("host") }) : t("remoteEntry");
2589
+ }, remoteLabel = status?.mode === "remote" ? t("activeRemote", { name: status.target?.name ?? t("host") }) : t("remoteEntry"), currentDeviceName = status?.deviceName ?? t("currentDevice");
2525
2590
  return React.createElement(
2526
2591
  React.Fragment,
2527
2592
  null,
@@ -2700,31 +2765,40 @@ Minimum version required to store current data is: ` + bestVersion + `.
2700
2765
  React.createElement(
2701
2766
  "div",
2702
2767
  { className: "dshRemoteSectionActions" },
2703
- status?.hostAuthorizationAvailable ? React.createElement(
2768
+ React.createElement(
2704
2769
  "div",
2705
- { className: "dshRemoteHostControlToggle" },
2706
- React.createElement("span", null, t("allowControlCurrentDevice")),
2707
- React.createElement("input", {
2708
- type: "checkbox",
2709
- role: "switch",
2710
- disabled: busy,
2711
- "aria-label": t("allowControlCurrentDevice"),
2712
- checked: status.host?.authorized === !0,
2713
- onChange: (event) => void setCurrentDeviceControl(event.target.checked)
2714
- })
2715
- ) : null,
2770
+ { className: "dshRemoteCurrentDeviceControl" },
2771
+ React.createElement(
2772
+ "div",
2773
+ { className: "dshRemoteCurrentDeviceTitle" },
2774
+ React.createElement("span", { className: "dshRemoteCurrentDeviceName" }, currentDeviceName),
2775
+ React.createElement("button", {
2776
+ type: "button",
2777
+ className: "dshRemoteAccountExit",
2778
+ disabled: busy,
2779
+ onClick: () => void logoutRemote()
2780
+ }, t("exitRemoteAccount"))
2781
+ ),
2782
+ status?.hostAuthorizationAvailable ? React.createElement(
2783
+ "div",
2784
+ { className: "dshRemoteHostControlToggle" },
2785
+ React.createElement("span", null, t("allowControlCurrentDevice")),
2786
+ React.createElement("input", {
2787
+ type: "checkbox",
2788
+ role: "switch",
2789
+ disabled: busy,
2790
+ "aria-label": t("allowControlCurrentDevice"),
2791
+ checked: status.host?.authorized === !0,
2792
+ onChange: (event) => void setCurrentDeviceControl(event.target.checked)
2793
+ })
2794
+ ) : null
2795
+ ),
2716
2796
  selectedHost === void 0 ? null : React.createElement("button", {
2717
2797
  type: "button",
2718
2798
  onClick: () => {
2719
2799
  setSelectedHost(void 0), setWorkspaces([]), setDirectory(void 0), setPath(""), setAddingWorkspace(!1), setError(void 0);
2720
2800
  }
2721
- }, t("backToHosts")),
2722
- React.createElement("button", {
2723
- type: "button",
2724
- className: "dshRemoteAccountExit",
2725
- disabled: busy,
2726
- onClick: () => void logoutRemote()
2727
- }, t("exitRemoteAccount"))
2801
+ }, t("backToHosts"))
2728
2802
  )
2729
2803
  ),
2730
2804
  selectedHost === void 0 ? React.createElement("div", { className: "dshRemoteHostList" }, devices.length === 0 ? React.createElement("p", null, t(busy ? "checkingConnection" : "noRemoteHosts")) : devices.map((device) => React.createElement(
@@ -2858,7 +2932,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
2858
2932
  setBusy(!0), setError(void 0);
2859
2933
  try {
2860
2934
  let action = () => props.control("mode.set", { mode, ...targetDeviceId === void 0 ? {} : { targetDeviceId } });
2861
- mode === "remote" ? await runRemoteProgress(connectHostProgressSteps, setProgress, progressRun, action) : await action(), window.location.reload();
2935
+ mode === "remote" ? await runRemoteProgress(connectHostProgressSteps(status?.preferredTransports), setProgress, progressRun, action) : await action(), window.location.reload();
2862
2936
  } catch (reason) {
2863
2937
  setError(messageOf(reason)), setBusy(!1);
2864
2938
  }
@@ -3089,7 +3163,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
3089
3163
  null,
3090
3164
  fact(t("connectionId"), detailValue(network.connectionId), !0),
3091
3165
  fact(t("connectedAt"), network.connectedAt === void 0 ? t("notProvided") : formatLocalTime(network.connectedAt)),
3092
- fact(t("preferredTransports"), network.preferredTransports.map((value) => value.toUpperCase()).join(" \u2192 ")),
3166
+ fact(t("preferredTransports"), network.preferredTransports.map((value) => transportLabel(value, t)).join(" \u2192 ")),
3093
3167
  fact(t("controlChannel"), `WebSocket \xB7 ${controlStateLabel}`),
3094
3168
  fact(t("controlAddress"), network.controlChannelUrl, !0)
3095
3169
  )
@@ -3159,7 +3233,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
3159
3233
  ".dshRemoteModeButton:is(button):hover{background:var(--dsw-alias-interactive-bg-hover)}",
3160
3234
  ".dshRemoteSidebarEntry{box-sizing:border-box;position:relative;min-width:0;display:block;overflow:hidden}.dshRemoteSidebarEntry .dshRemoteModeButton{box-sizing:border-box;width:100%;min-width:0}.dshRemoteSidebarEntry.isWide{width:calc(100% + 8px);height:34px;margin:4px -4px}.dshRemoteSidebarEntry.isWide .dshRemoteModeButton{height:34px;min-height:34px;padding:6px 48px 6px 10px;border-radius:12px}.dshRemoteSidebarEntry.isRail{width:36px;height:54px}.dshRemoteSidebarEntry.isRail .dshRemoteModeButton{width:36px;height:36px;min-height:36px;justify-content:center;gap:0;margin:8px 0 10px;padding:0;border-radius:50%}.dshRemoteSidebarEntry.isActive .dshRemoteModeButton{color:var(--dsw-alias-label-secondary);background:transparent}.dshRemoteSidebarLabel{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dshRemoteExitLink{position:absolute;top:50%;right:10px;transform:translateY(-50%);white-space:nowrap;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:0;font:inherit;font-size:12px;line-height:20px;cursor:pointer}.dshRemoteExitLink:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteExitLink:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;border-radius:2px}.dshRemoteExitLink:disabled{opacity:.45;cursor:default;text-decoration:none}",
3161
3235
  ".dshRemoteComputerIcon{box-sizing:border-box;width:18px;height:18px;flex:0 0 18px;color:var(--dsw-alias-label-secondary)}",
3162
- '.dshRemoteSessionHeader{position:fixed;z-index:25;top:12px;left:50%;transform:translateX(-50%);max-width:calc(100vw - 360px);height:28px;display:inline-flex;align-items:center;gap:7px;color:var(--dsw-alias-label-secondary);font-size:12px;white-space:nowrap}.dshRemoteSessionHeader>svg{width:15px;height:15px;flex:0 0 auto}.dshRemoteSessionTarget{min-width:0;max-width:260px;overflow:hidden;text-overflow:ellipsis}.dshRemoteNetwork{flex:0 0 auto;border:0;background:transparent;color:inherit;font:inherit;padding:3px 2px;display:inline-flex;align-items:center;gap:5px;cursor:pointer}.dshRemoteNetwork:hover:not(:disabled){color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteNetwork:disabled{cursor:default}.dshRemoteNetwork>i{width:6px;height:6px;border-radius:50%;background:var(--dsw-alias-label-tertiary)}.dshRemoteNetwork.isOnline>i{background:var(--dsw-alias-state-success-primary)}.dshRemoteNetwork.isOffline{color:var(--dsw-alias-state-error-primary)}.dshRemoteNetwork.isOffline>i{background:currentColor}.dshRemoteEncrypted{flex:0 0 auto;color:var(--dsw-alias-label-tertiary)}.dshRemoteHeaderExitLink{flex:0 0 auto;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:3px 2px;font:inherit;text-decoration:none;cursor:pointer}.dshRemoteHeaderExitLink:hover{text-decoration:underline;color:var(--dsw-alias-label-primary)}.dshRemoteHeaderExitLink:disabled{opacity:.45;cursor:default;text-decoration:none}.dshRemoteNetwork:focus-visible,.dshRemoteHeaderExitLink:focus-visible,.dshRemoteRoutePanel>header button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.dshRemoteRouteBackdrop{position:fixed;inset:0;z-index:26}.dshRemoteRoutePanel{box-sizing:border-box;position:absolute;top:48px;right:28px;width:min(680px,calc(100vw - 32px));max-height:calc(100vh - 72px);overflow:auto;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;padding:16px;white-space:normal}.dshRemoteRoutePanel>header{position:sticky;top:-16px;z-index:1;display:flex;align-items:center;justify-content:space-between;margin:-16px -16px 0;padding:16px;background:var(--dsw-alias-bg-layer-1)}.dshRemoteRoutePanel>header strong{font-size:14px}.dshRemoteRoutePanel>header button{width:28px;height:28px;border:0;border-radius:7px;background:transparent;color:inherit;font-size:20px;cursor:pointer}.dshRemoteRoutePanel>header button:hover{background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteRoutePanel ol{display:flex;align-items:stretch;margin:12px 0 0;padding:0 0 16px;border-bottom:1px solid var(--dsw-alias-border-l2);list-style:none}.dshRemoteRoutePanel li{position:relative;min-width:0;flex:1;display:flex;flex-direction:column;gap:4px;padding-right:20px}.dshRemoteRoutePanel li:not(:last-child)::after{content:"\u2192";position:absolute;right:7px;top:21px;color:var(--dsw-alias-label-tertiary)}.dshRemoteRoutePanel li small{color:var(--dsw-alias-label-tertiary)}.dshRemoteRoutePanel li strong,.dshRemoteRoutePanel li span{overflow:hidden;text-overflow:ellipsis}.dshRemoteRoutePanel li strong{font-size:13px}.dshRemoteRoutePanel li span{color:var(--dsw-alias-label-secondary);font-size:11px}.dshRemoteRouteSection{padding-top:16px}.dshRemoteRouteSection h3{margin:0 0 10px;font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary)}.dshRemoteRouteSection dl{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 24px;margin:0}.dshRemoteRouteSection dl>div{min-width:0;display:grid;grid-template-columns:minmax(104px,auto) minmax(0,1fr);gap:10px;padding:7px 0;border-bottom:1px solid var(--dsw-alias-border-l2);font-size:12px;line-height:1.45}.dshRemoteRouteSection dt{color:var(--dsw-alias-label-tertiary)}.dshRemoteRouteSection dd{min-width:0;margin:0;text-align:right;overflow-wrap:anywhere}.dshRemoteRouteSection dd.isMono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}.dshRemoteRoutePanel>p{margin:16px 0 0;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}@media(max-width:620px){.dshRemoteSessionHeader{top:8px;max-width:calc(100vw - 112px)}.dshRemoteSessionHeader>svg{display:none}.dshRemoteSessionTarget{max-width:130px}.dshRemoteEncrypted{display:none}.dshRemoteRoutePanel{top:42px;right:12px;max-height:calc(100vh - 56px)}.dshRemoteRoutePanel ol{flex-direction:column;gap:18px}.dshRemoteRoutePanel li:not(:last-child)::after{content:"\u2193";top:auto;right:auto;bottom:-16px;left:3px}.dshRemoteRouteSection dl{grid-template-columns:1fr}}',
3236
+ '.dshRemoteSessionHeader{position:fixed;z-index:25;top:12px;left:50%;transform:translateX(-50%);max-width:calc(100vw - 360px);height:28px;display:inline-flex;align-items:center;gap:7px;color:var(--dsw-alias-label-secondary);font-size:12px;white-space:nowrap}.dshRemoteSessionHeader>svg{width:15px;height:15px;flex:0 0 auto}.dshRemoteSessionTarget{min-width:0;max-width:260px;overflow:hidden;text-overflow:ellipsis}.dshRemoteNetwork{flex:0 0 auto;border:0;background:transparent;color:inherit;font:inherit;padding:3px 2px;display:inline-flex;align-items:center;gap:5px;cursor:pointer}.dshRemoteNetwork:hover:not(:disabled){color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteNetwork:disabled{cursor:default}.dshRemoteNetwork>i{width:6px;height:6px;border-radius:50%;background:var(--dsw-alias-label-tertiary)}.dshRemoteNetwork.isOnline>i{background:var(--dsw-alias-state-success-primary)}.dshRemoteNetwork.isOffline{color:var(--dsw-alias-state-error-primary)}.dshRemoteNetwork.isOffline>i{background:currentColor}.dshRemoteEncrypted{flex:0 0 auto;color:var(--dsw-alias-label-tertiary)}.dshRemoteHeaderExitLink{flex:0 0 auto;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:3px 2px;font:inherit;text-decoration:none;cursor:pointer}.dshRemoteHeaderExitLink:hover{text-decoration:underline;color:var(--dsw-alias-label-primary)}.dshRemoteHeaderExitLink:disabled{opacity:.45;cursor:default;text-decoration:none}.dshRemoteNetwork:focus-visible,.dshRemoteHeaderExitLink:focus-visible,.dshRemoteRoutePanel>header button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.dshRemoteRouteBackdrop{position:fixed;inset:0;z-index:26}.dshRemoteRoutePanel{box-sizing:border-box;position:absolute;top:48px;right:28px;width:min(680px,calc(100vw - 32px));max-height:calc(100vh - 72px);overflow:auto;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;padding:16px;white-space:normal}.dshRemoteRoutePanel>header{position:sticky;top:-16px;z-index:1;display:flex;align-items:center;justify-content:space-between;margin:-16px -16px 0;padding:16px;background:var(--dsw-alias-bg-layer-1)}.dshRemoteRoutePanel>header strong{font-size:14px}.dshRemoteRoutePanel>header button{width:28px;height:28px;border:0;border-radius:7px;background:transparent;color:inherit;font-size:20px;cursor:pointer}.dshRemoteRoutePanel>header button:hover{background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteRoutePanel ol{display:flex;align-items:stretch;margin:12px 0 0;padding:0 0 16px;border-bottom:1px solid var(--dsw-alias-border-l2);list-style:none}.dshRemoteRoutePanel li{position:relative;min-width:0;flex:1;display:flex;flex-direction:column;gap:4px;padding-right:20px}.dshRemoteRoutePanel li:not(:last-child)::after{content:"\u2192";position:absolute;right:7px;top:21px;color:var(--dsw-alias-label-tertiary)}.dshRemoteRoutePanel li small{color:var(--dsw-alias-label-tertiary)}.dshRemoteRoutePanel li strong,.dshRemoteRoutePanel li span{overflow:hidden;text-overflow:ellipsis}.dshRemoteRoutePanel li strong{font-size:13px}.dshRemoteRoutePanel li span{color:var(--dsw-alias-label-secondary);font-size:11px}.dshRemoteRouteSection{padding-top:16px}.dshRemoteRouteSection h3{margin:0 0 10px;font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary)}.dshRemoteRouteSection dl{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 24px;margin:0}.dshRemoteRouteSection dl>div{min-width:0;display:grid;grid-template-columns:minmax(104px,auto) minmax(0,1fr);gap:10px;padding:7px 0;border-bottom:1px solid var(--dsw-alias-border-l2);font-size:12px;line-height:1.45}.dshRemoteRouteSection dt{color:var(--dsw-alias-label-tertiary)}.dshRemoteRouteSection dd{min-width:0;margin:0;text-align:right;overflow-wrap:anywhere}.dshRemoteRouteSection dd.isMono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}.dshRemoteRoutePanel>p{margin:16px 0 0;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}@media(max-width:620px){.dshRemoteSessionHeader{top:8px;max-width:calc(100vw - 112px)}.dshRemoteSessionHeader>svg{display:none}.dshRemoteSessionTarget{max-width:130px}.dshRemoteEncrypted{display:none}.dshRemoteRoutePanel{top:42px;right:12px;max-height:calc(100vh - 56px)}.dshRemoteRoutePanel ol{flex-direction:column;gap:18px}.dshRemoteRoutePanel li:not(:last-child)::after{content:"\u2193";top:auto;right:auto;bottom:-16px;left:3px}.dshRemoteRouteSection dl{grid-template-columns:1fr}.dshRemoteRouteSection dl>div{grid-template-columns:1fr;gap:2px}.dshRemoteRouteSection dd{text-align:left}}',
3163
3237
  ".dshRemoteSessionHeader{left:auto;right:148px;transform:none;max-width:calc(100vw - 420px)}@media(max-width:760px){.dshRemoteSessionHeader{left:auto;right:104px;transform:none;max-width:calc(100vw - 124px)}}",
3164
3238
  ".dshRemoteModeButton:focus-visible,.dshRemotePage button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}",
3165
3239
  ".dshRemotePage{width:min(720px,100%);max-height:min(760px,calc(100vh - 40px));display:flex;flex-direction:column;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:14px;overflow:hidden;animation:dshRemotePageIn .18s cubic-bezier(.25,1,.5,1)}",
@@ -3169,7 +3243,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
3169
3243
  ".dshRemoteSectionHeading>.dshRemoteAddWorkspace{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;padding:0;border-radius:50%;font-size:20px;line-height:1}.dshRemoteSectionHeading>.dshRemoteAddWorkspace:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}",
3170
3244
  ".dshRemoteHostList{display:flex;flex-direction:column;border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteHostList>button{min-height:58px;display:flex;align-items:center;justify-content:space-between;gap:16px;text-align:left;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);background:transparent;padding:10px 4px;cursor:pointer}.dshRemoteHostList>button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteHostList>button:disabled{opacity:.5;cursor:default}.dshRemoteHostList>button>span{min-width:0;display:flex;flex-direction:column;gap:3px}.dshRemoteHostList>button strong{font-size:14px;font-weight:500}.dshRemoteHostList small,.dshRemoteSelectedHost small{color:var(--dsw-alias-label-secondary);font-size:12px}",
3171
3245
  ".dshRemoteSelectedHost{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 14px;border-radius:10px;background:var(--dsw-alias-bg-layer-2)}",
3172
- ".dshRemoteProgress{display:flex;flex-direction:column;gap:8px;margin:12px 0;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2)}.dshRemoteProgressHeader{display:flex;align-items:center;justify-content:space-between;gap:12px}.dshRemoteProgressHeader strong{font-size:13px;font-weight:600}.dshRemoteProgressHeader span{color:var(--dsw-alias-label-secondary);font-size:12px}.dshRemoteProgressBar{height:6px;overflow:hidden;border-radius:999px;background:var(--dsw-alias-bg-layer-3)}.dshRemoteProgressBar>span{display:block;height:100%;border-radius:inherit;background:var(--dsw-alias-brand-primary);transition:width .22s ease-out}.dshRemoteProgress p{margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.45}@media(prefers-reduced-motion:reduce){.dshRemoteProgressBar>span{transition:none}}",
3246
+ ".dshRemoteProgress{display:flex;flex-direction:column;gap:8px;margin:12px 0;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2)}.dshRemoteProgressHeader{display:flex;align-items:center;justify-content:space-between;gap:12px}.dshRemoteProgressHeader strong{font-size:13px;font-weight:600}.dshRemoteProgressHeader span{color:var(--dsw-alias-label-secondary);font-size:12px}.dshRemoteProgressBar{height:6px;overflow:hidden;border-radius:999px;background:var(--dsw-alias-bg-layer-3)}.dshRemoteProgressBar>span{display:block;height:100%;border-radius:inherit;background:var(--dsw-alias-brand-primary);transition:width .22s ease-out}.dshRemoteProgress p{margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.45}.dshRemoteProgressRoute{font-weight:500}.dshRemoteProgressRoute .isActive{color:var(--dsw-alias-state-success-primary);font-weight:700}.dshRemoteProgressRouteArrow{color:var(--dsw-alias-label-tertiary)}@media(prefers-reduced-motion:reduce){.dshRemoteProgressBar>span{transition:none}}",
3173
3247
  '.dshRemoteBrowser{display:flex;flex-direction:column}.dshRemoteCrumbs{display:flex;align-items:center;gap:4px;overflow:auto;padding:2px 0 10px}.dshRemoteCrumbs>button{flex:0 0 auto;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:5px 7px;border-radius:6px;cursor:pointer}.dshRemoteCrumbs>button:not(:last-child)::after{content:" /";color:var(--dsw-alias-label-tertiary)}.dshRemoteCrumbs>button:disabled{color:var(--dsw-alias-label-primary);font-weight:600}',
3174
3248
  ".dshRemoteDirectoryList{min-height:72px;display:flex;flex-direction:column;border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteDirectoryList>button{min-height:52px;display:grid;grid-template-columns:auto 1fr;column-gap:10px;text-align:left;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);background:transparent;padding:8px 4px;cursor:pointer}.dshRemoteDirectoryList>button:hover,.dshRemoteDirectoryList>button.isSelected{background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteDirectoryList>button.isSelected{color:var(--dsw-alias-label-primary)}.dshRemoteDirectoryList>button>span:first-child{grid-row:1/3}.dshRemoteDirectoryList>button>small{grid-column:2;color:var(--dsw-alias-label-secondary);overflow:hidden;text-overflow:ellipsis}.dshRemoteDirectoryList>p,.dshRemoteHint{margin:12px 0;color:var(--dsw-alias-label-secondary);font-size:13px}",
3175
3249
  ".dshRemoteFolderBrowser{margin-top:14px}.dshRemoteFolderBrowser>p,.dshRemoteFolderList>p{margin:12px 0;color:var(--dsw-alias-label-secondary);font-size:13px}.dshRemoteFolderList{max-height:260px;overflow:auto;border-block:1px solid var(--dsw-alias-border-l2)}.dshRemoteFolderList>button{width:100%;min-height:42px;display:flex;align-items:center;gap:9px;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);background:transparent;padding:7px 6px;text-align:left;cursor:pointer}.dshRemoteFolderList>button:hover{background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteFolderBrowser>small{display:block;margin-top:8px;color:var(--dsw-alias-state-warn-label)}",
@@ -3180,8 +3254,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
3180
3254
  ".dshRemoteClientLogin{width:min(440px,100%);display:flex;flex-direction:column;gap:8px}.dshRemoteClientLogin input{min-height:40px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:inherit;padding:0 12px;font:inherit}.dshRemoteClientLogin button{align-self:flex-start;min-height:40px;border:0;border-radius:8px;background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-1);padding:8px 16px;cursor:pointer}",
3181
3255
  ".dshRemoteQrLogin{width:min(440px,100%);display:flex;flex-direction:column;align-items:center;gap:8px;padding:6px 0 2px;text-align:center}.dshRemoteQrLogin img,.dshRemoteQrPlaceholder{box-sizing:border-box;width:200px;height:200px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:#fff;padding:8px}.dshRemoteQrOpen{display:flex;flex-direction:column;align-items:center;gap:5px;color:var(--dsw-alias-label-secondary);font-size:12px;text-decoration:none}.dshRemoteQrOpen:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteQrOpen:hover img{border-color:var(--dsw-alias-label-dimmed)}.dshRemoteQrOpen:focus-visible{border-radius:12px;outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}.dshRemoteQrPlaceholder{display:flex;align-items:center;justify-content:center;color:var(--dsw-alias-label-secondary)}.dshRemoteQrLogin>strong{font-size:14px}.dshRemoteQrLogin>p{max-width:48ch;margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}.dshRemoteQrLogin>.dshRemoteServiceAddress{margin-top:2px;color:var(--dsw-alias-label-tertiary)}.dshRemoteServiceAddress>a{color:var(--dsw-alias-label-secondary);text-decoration:none}.dshRemoteServiceAddress>a:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteQrLogin>button,.dshRemoteClientLogin>.dshRemoteLoginSwitch{min-height:32px;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:4px 8px;font:inherit;font-size:12px;cursor:pointer}.dshRemoteQrLogin>button:hover,.dshRemoteClientLogin>.dshRemoteLoginSwitch:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteClientLogin>.dshRemoteLoginSwitch{align-self:flex-start;background:transparent;color:var(--dsw-alias-label-secondary);padding-left:0}",
3182
3256
  ".dshRemoteEnable{box-sizing:border-box;width:100%;min-height:388px}.dshRemoteLoginHeading{max-width:100%;display:flex;align-items:baseline;gap:10px;overflow:hidden;white-space:nowrap}.dshRemoteLoginTitle{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dshRemoteLoginHeading>span{flex:0 0 auto;color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:400}.dshRemoteLoginTabs{width:100%}.dshRemoteLoginTabs>button{min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dshRemoteLoginTabs>button.isActive::after{right:0;left:0;border-radius:0}.dshRemoteClientLogin,.dshRemoteQrLogin{box-sizing:border-box;width:min(440px,100%);height:300px;min-height:300px;align-self:center}.dshRemoteClientLogin{align-items:stretch;padding-top:16px}.dshRemoteClientLogin>button{align-self:stretch;width:100%}.dshRemoteQrLogin{padding-top:12px}",
3183
- '.dshRemoteHostControlToggle{display:flex;align-items:center;gap:8px;color:var(--dsw-alias-label-secondary);font-size:12px;white-space:nowrap;cursor:default}.dshRemoteHostControlToggle>input{appearance:none;position:relative;width:38px;height:22px;flex:0 0 auto;margin:0;border:1px solid var(--dsw-alias-label-secondary);border-radius:999px;background:var(--dsw-alias-bg-layer-3);cursor:pointer;box-shadow:inset 0 0 0 1px var(--dsw-alias-border-l2);transition:background .16s ease-out,border-color .16s ease-out,box-shadow .16s ease-out}.dshRemoteHostControlToggle>input::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--dsw-alias-label-secondary);transition:transform .16s ease-out,background .16s ease-out}.dshRemoteHostControlToggle>input:checked{border-color:var(--dsw-alias-state-success-primary);background:var(--dsw-alias-state-success-primary);box-shadow:none}.dshRemoteHostControlToggle>input:checked::after{transform:translateX(16px);background:var(--dsw-alias-bg-layer-1)}.dshRemoteHostControlToggle>input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.dshRemoteHostControlToggle>input:disabled{opacity:.5;cursor:default}@media(prefers-reduced-motion:reduce){.dshRemoteHostControlToggle>input,.dshRemoteHostControlToggle>input::after{transition:none}}',
3184
- ".dshRemoteAccountExit{flex:0 0 auto}.dshRemoteAccountExit:disabled{opacity:.5;cursor:default;text-decoration:none}",
3257
+ '.dshRemoteCurrentDeviceControl{min-width:0;display:flex;align-items:center;gap:14px}.dshRemoteCurrentDeviceTitle{min-width:0;display:flex;align-items:center;gap:8px}.dshRemoteCurrentDeviceName{min-width:0;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary);font-size:12px;font-weight:500;line-height:1.5}.dshRemoteHostControlToggle{display:flex;align-items:center;gap:8px;color:var(--dsw-alias-label-secondary);font-size:12px;white-space:nowrap;cursor:default}.dshRemoteHostControlToggle>input{appearance:none;position:relative;width:38px;height:22px;flex:0 0 auto;margin:0;border:1px solid var(--dsw-alias-label-secondary);border-radius:999px;background:var(--dsw-alias-bg-layer-3);cursor:pointer;box-shadow:inset 0 0 0 1px var(--dsw-alias-border-l2);transition:background .16s ease-out,border-color .16s ease-out,box-shadow .16s ease-out}.dshRemoteHostControlToggle>input::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--dsw-alias-label-secondary);transition:transform .16s ease-out,background .16s ease-out}.dshRemoteHostControlToggle>input:checked{border-color:var(--dsw-alias-state-success-primary);background:var(--dsw-alias-state-success-primary);box-shadow:none}.dshRemoteHostControlToggle>input:checked::after{transform:translateX(16px);background:var(--dsw-alias-bg-layer-1)}.dshRemoteHostControlToggle>input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.dshRemoteHostControlToggle>input:disabled{opacity:.5;cursor:default}@media(prefers-reduced-motion:reduce){.dshRemoteHostControlToggle>input,.dshRemoteHostControlToggle>input::after{transition:none}}',
3258
+ ".dshRemoteAccountExit{flex:0 0 auto;border:0;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;padding:5px 0;font-size:12px;line-height:1.5;white-space:nowrap}.dshRemoteAccountExit:hover:not(:disabled){color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteAccountExit:disabled{opacity:.5;cursor:default;text-decoration:none}",
3185
3259
  ".dshRemoteLocalLink{align-self:flex-start;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:4px 0;cursor:pointer}.dshRemoteLocalLink:hover{color:var(--dsw-alias-label-primary)}",
3186
3260
  "@keyframes dshRemotePageIn{from{opacity:0;transform:translateY(6px) scale(.99)}to{opacity:1;transform:none}}@media(prefers-reduced-motion:reduce){.dshRemotePage{animation:none}}@media(max-width:620px){.dshRemoteBackdrop{padding:12px}.dshRemotePage{max-height:calc(100vh - 24px)}.dshRemotePageHeader{padding:12px 16px}.dshRemoteSectionHeading{align-items:flex-start;flex-direction:column;gap:8px}.dshRemoteSectionActions{width:100%;justify-content:space-between}.dshRemotePageBody{padding:20px 16px}.dshRemoteOpenBar{align-items:flex-end}.dshRemoteOpenBar>button{min-height:48px}}",
3187
3261
  ".dshRemoteBackdrop{position:fixed;inset:0;z-index:1000;background:var(--dsw-alias-bg-mask-3);display:grid;place-items:center;padding:20px}",
@@ -3240,14 +3314,15 @@ Minimum version required to store current data is: ` + bestVersion + `.
3240
3314
  }, "dsh-remote: resume selected workspace"), ctx.inject(["fileViewer"], (fileViewerContext) => {
3241
3315
  let viewer = fileViewerContext.get("fileViewer");
3242
3316
  viewer !== void 0 && fileViewerContext.effect(() => {
3243
- let active = !0, unregister, sync = async () => {
3317
+ let active = !0, unregister, latestSaveAsAllowed = !1, sync = async () => {
3244
3318
  try {
3245
3319
  let status = await control("status");
3246
3320
  if (!active) return;
3247
3321
  let supported = shouldUseRemoteFileViewer(status);
3248
- supported && unregister === void 0 ? unregister = viewer.registerContentProvider(createRemoteFileContentProvider(
3249
- (endpoint, payload) => control(endpoint, payload)
3250
- )) : !supported && unregister !== void 0 && (unregister(), unregister = void 0);
3322
+ latestSaveAsAllowed = shouldAllowRemoteFileSaveAs(status), supported && unregister === void 0 ? unregister = viewer.registerContentProvider(createRemoteFileContentProvider(
3323
+ (endpoint, payload) => control(endpoint, payload),
3324
+ { saveAsAllowed: () => latestSaveAsAllowed, saveAsMaxBytes: REMOTE_FILE_SAVE_AS_MAX_BYTES }
3325
+ )) : !supported && unregister !== void 0 && (unregister(), unregister = void 0, latestSaveAsAllowed = !1);
3251
3326
  } catch {
3252
3327
  }
3253
3328
  };
@@ -3276,8 +3351,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
3276
3351
  })
3277
3352
  }, RemoteWorkspaceAction)), ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
3278
3353
  name: "settings.plugin.item",
3279
- key: "dsh-remote",
3280
- id: "dsh-remote",
3354
+ key: "ds-harness-remote",
3355
+ id: "ds-harness-remote",
3281
3356
  order: 30,
3282
3357
  locale: localeNamespace,
3283
3358
  inject: () => ({ control })