ds-harness-remote 0.3.22 → 0.3.23
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.github.js +102 -8
- package/dist/client.js +102 -8
- package/dist/client.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +9 -5
package/dist/client.github.js
CHANGED
|
@@ -1771,6 +1771,20 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
1771
1771
|
openWorkspace: "Open workspace",
|
|
1772
1772
|
openingWorkspace: "Opening\u2026",
|
|
1773
1773
|
loadingDirectory: "Loading directories\u2026",
|
|
1774
|
+
remoteProgressCheckingHost: "Checking Host",
|
|
1775
|
+
remoteProgressCheckingHostDetail: "Finding the selected device and checking whether it is online.",
|
|
1776
|
+
remoteProgressAuthorizingPeer: "Verifying authorization",
|
|
1777
|
+
remoteProgressAuthorizingPeerDetail: "Confirming account membership and pinned Host identity.",
|
|
1778
|
+
remoteProgressOpeningChannel: "Opening encrypted channel",
|
|
1779
|
+
remoteProgressOpeningChannelDetail: "Trying LAN, P2P, TURN, then Relay if needed.",
|
|
1780
|
+
remoteProgressLoadingWorkspaces: "Loading workspaces",
|
|
1781
|
+
remoteProgressLoadingWorkspacesDetail: "Reading the remote Harness workspace list through the tunnel.",
|
|
1782
|
+
remoteProgressOpeningWorkspace: "Opening workspace",
|
|
1783
|
+
remoteProgressOpeningWorkspaceDetail: "Asking the Host to prepare the selected working directory.",
|
|
1784
|
+
remoteProgressSwitchingWorkspace: "Switching interface",
|
|
1785
|
+
remoteProgressSwitchingWorkspaceDetail: "Handing the remote workspace to the local Harness UI.",
|
|
1786
|
+
remoteProgressReady: "Ready",
|
|
1787
|
+
remoteProgressReadyDetail: "The remote Host is connected and encrypted.",
|
|
1774
1788
|
backToHosts: "Choose another Host",
|
|
1775
1789
|
currentDirectory: "Selected directory",
|
|
1776
1790
|
directoryTruncated: "Only part of this directory could be shown.",
|
|
@@ -1941,6 +1955,20 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
1941
1955
|
openWorkspace: "\u6253\u5F00\u5DE5\u4F5C\u533A",
|
|
1942
1956
|
openingWorkspace: "\u6B63\u5728\u6253\u5F00\u2026",
|
|
1943
1957
|
loadingDirectory: "\u6B63\u5728\u52A0\u8F7D\u76EE\u5F55\u2026",
|
|
1958
|
+
remoteProgressCheckingHost: "\u6B63\u5728\u68C0\u67E5 Host",
|
|
1959
|
+
remoteProgressCheckingHostDetail: "\u6B63\u5728\u67E5\u627E\u6240\u9009\u8BBE\u5907\u5E76\u786E\u8BA4\u662F\u5426\u5728\u7EBF\u3002",
|
|
1960
|
+
remoteProgressAuthorizingPeer: "\u6B63\u5728\u9A8C\u8BC1\u6388\u6743",
|
|
1961
|
+
remoteProgressAuthorizingPeerDetail: "\u6B63\u5728\u786E\u8BA4\u8D26\u53F7\u6210\u5458\u5173\u7CFB\u548C\u5DF2\u56FA\u5B9A\u7684 Host \u8EAB\u4EFD\u3002",
|
|
1962
|
+
remoteProgressOpeningChannel: "\u6B63\u5728\u5EFA\u7ACB\u52A0\u5BC6\u901A\u9053",
|
|
1963
|
+
remoteProgressOpeningChannelDetail: "\u4F9D\u6B21\u5C1D\u8BD5\u5C40\u57DF\u7F51\u3001P2P\u3001TURN\uFF0C\u5FC5\u8981\u65F6\u56DE\u843D\u5230 Relay\u3002",
|
|
1964
|
+
remoteProgressLoadingWorkspaces: "\u6B63\u5728\u52A0\u8F7D\u5DE5\u4F5C\u533A",
|
|
1965
|
+
remoteProgressLoadingWorkspacesDetail: "\u901A\u8FC7\u96A7\u9053\u8BFB\u53D6\u8FDC\u7AEF Harness \u5DE5\u4F5C\u533A\u5217\u8868\u3002",
|
|
1966
|
+
remoteProgressOpeningWorkspace: "\u6B63\u5728\u6253\u5F00\u5DE5\u4F5C\u533A",
|
|
1967
|
+
remoteProgressOpeningWorkspaceDetail: "\u6B63\u5728\u8BF7\u6C42 Host \u51C6\u5907\u6240\u9009\u5DE5\u4F5C\u76EE\u5F55\u3002",
|
|
1968
|
+
remoteProgressSwitchingWorkspace: "\u6B63\u5728\u5207\u6362\u754C\u9762",
|
|
1969
|
+
remoteProgressSwitchingWorkspaceDetail: "\u6B63\u5728\u628A\u8FDC\u7AEF\u5DE5\u4F5C\u533A\u4EA4\u7ED9\u672C\u5730 Harness UI\u3002",
|
|
1970
|
+
remoteProgressReady: "\u5DF2\u5C31\u7EEA",
|
|
1971
|
+
remoteProgressReadyDetail: "\u8FDC\u7AEF Host \u5DF2\u8FDE\u63A5\uFF0C\u7AEF\u5230\u7AEF\u52A0\u5BC6\u5DF2\u5EFA\u7ACB\u3002",
|
|
1944
1972
|
backToHosts: "\u9009\u62E9\u5176\u4ED6\u4E3B\u673A",
|
|
1945
1973
|
currentDirectory: "\u5DF2\u9009\u76EE\u5F55",
|
|
1946
1974
|
directoryTruncated: "\u76EE\u5F55\u5185\u5BB9\u8F83\u591A\uFF0C\u76EE\u524D\u53EA\u663E\u793A\u4E86\u4E00\u90E8\u5206\u3002",
|
|
@@ -2054,6 +2082,58 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2054
2082
|
id: clientModuleId,
|
|
2055
2083
|
factory: (require2) => {
|
|
2056
2084
|
let module = { exports: {} }, React = require2("react"), inject = ["connection", "slots", "locale", "workspaces", "sessions"];
|
|
2085
|
+
function RemoteProgressView(props) {
|
|
2086
|
+
let progress = props.progress;
|
|
2087
|
+
if (progress === void 0) return null;
|
|
2088
|
+
let percent = Math.max(0, Math.min(100, Math.round(progress.percent)));
|
|
2089
|
+
return React.createElement(
|
|
2090
|
+
"div",
|
|
2091
|
+
{
|
|
2092
|
+
className: "dshRemoteProgress",
|
|
2093
|
+
role: "status",
|
|
2094
|
+
"aria-live": "polite"
|
|
2095
|
+
},
|
|
2096
|
+
React.createElement(
|
|
2097
|
+
"div",
|
|
2098
|
+
{ className: "dshRemoteProgressHeader" },
|
|
2099
|
+
React.createElement("strong", null, props.t(progress.label)),
|
|
2100
|
+
React.createElement("span", null, `${percent}%`)
|
|
2101
|
+
),
|
|
2102
|
+
React.createElement("div", {
|
|
2103
|
+
className: "dshRemoteProgressBar",
|
|
2104
|
+
role: "progressbar",
|
|
2105
|
+
"aria-valuemin": 0,
|
|
2106
|
+
"aria-valuemax": 100,
|
|
2107
|
+
"aria-valuenow": percent,
|
|
2108
|
+
"aria-label": props.t(progress.label)
|
|
2109
|
+
}, React.createElement("span", { style: { width: `${percent}%` } })),
|
|
2110
|
+
React.createElement("p", null, props.t(progress.detail))
|
|
2111
|
+
);
|
|
2112
|
+
}
|
|
2113
|
+
async function runRemoteProgress(steps, setProgress, progressRun, action) {
|
|
2114
|
+
let runId = progressRun.current + 1;
|
|
2115
|
+
progressRun.current = runId;
|
|
2116
|
+
let apply2 = (next) => {
|
|
2117
|
+
progressRun.current === runId && setProgress(next);
|
|
2118
|
+
}, [first, ...rest] = steps;
|
|
2119
|
+
first !== void 0 && apply2(first);
|
|
2120
|
+
let timers = rest.map((step) => window.setTimeout(() => apply2(step), step.delayMs ?? 0));
|
|
2121
|
+
try {
|
|
2122
|
+
let result = await action();
|
|
2123
|
+
return apply2({ label: "remoteProgressReady", detail: "remoteProgressReadyDetail", percent: 100 }), await new Promise((resolve) => window.setTimeout(resolve, 220)), result;
|
|
2124
|
+
} finally {
|
|
2125
|
+
timers.forEach((timer) => window.clearTimeout(timer)), progressRun.current === runId && setProgress(void 0);
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
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 = [
|
|
2134
|
+
{ label: "remoteProgressOpeningWorkspace", detail: "remoteProgressOpeningWorkspaceDetail", percent: 30 },
|
|
2135
|
+
{ label: "remoteProgressSwitchingWorkspace", detail: "remoteProgressSwitchingWorkspaceDetail", percent: 74, delayMs: 520 }
|
|
2136
|
+
];
|
|
2057
2137
|
function RemotePluginOptions(props) {
|
|
2058
2138
|
let { t } = props, [open, setOpen] = React.useState(!1), [serverUrl, setServerUrl] = React.useState(""), role = "host", [registrationCode, setRegistrationCode] = React.useState(""), [associations, setAssociations] = React.useState({}), [loaded, setLoaded] = React.useState(!1), [writable, setWritable] = React.useState(!1), [busy, setBusy] = React.useState(!1), [reconnectBusy, setReconnectBusy] = React.useState(!1), [hostStatus, setHostStatus] = React.useState(void 0), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0), [settingsView, setSettingsView] = React.useState(void 0), persistedServerUrl = settingsView?.config.serverUrl ?? "https://dsh.r2049.cn", association = associations.client ?? associations.host, serverDirty = settingsView !== void 0 && serverUrl !== persistedServerUrl, draftDirty = serverDirty, applyView = (view) => {
|
|
2059
2139
|
setSettingsView(view), setServerUrl(view.config.serverUrl ?? "https://dsh.r2049.cn"), setAssociations(view.associations ?? (view.association === void 0 ? {} : { host: view.association })), setWritable(view.writable), setLoaded(!0);
|
|
@@ -2282,7 +2362,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2282
2362
|
);
|
|
2283
2363
|
}
|
|
2284
2364
|
function RemoteWorkspaceAction(props) {
|
|
2285
|
-
let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [selectedHost, setSelectedHost] = React.useState(void 0), [workspaces, setWorkspaces] = React.useState([]), [directory, setDirectory] = React.useState(void 0), [path, setPath] = React.useState(""), [addingWorkspace, setAddingWorkspace] = React.useState(!1), [busy, setBusy] = React.useState(!1), [needsAuthorization, setNeedsAuthorization] = React.useState(!1), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [loginMethod, setLoginMethod] = React.useState(props.preferredQrProvider), [loginMethodManuallySelected, setLoginMethodManuallySelected] = React.useState(!1), [qrSession, setQrSession] = React.useState(void 0), [qrImage, setQrImage] = React.useState(void 0), [qrExpired, setQrExpired] = React.useState(!1), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0);
|
|
2365
|
+
let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [selectedHost, setSelectedHost] = React.useState(void 0), [workspaces, setWorkspaces] = React.useState([]), [directory, setDirectory] = React.useState(void 0), [path, setPath] = React.useState(""), [addingWorkspace, setAddingWorkspace] = React.useState(!1), [busy, setBusy] = React.useState(!1), [needsAuthorization, setNeedsAuthorization] = React.useState(!1), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [loginMethod, setLoginMethod] = React.useState(props.preferredQrProvider), [loginMethodManuallySelected, setLoginMethodManuallySelected] = React.useState(!1), [qrSession, setQrSession] = React.useState(void 0), [qrImage, setQrImage] = React.useState(void 0), [qrExpired, setQrExpired] = React.useState(!1), [progress, setProgress] = React.useState(void 0), progressRun = React.useRef(0), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0);
|
|
2286
2366
|
React.useEffect(() => {
|
|
2287
2367
|
if (!open) return;
|
|
2288
2368
|
let closeOnEscape = (event) => {
|
|
@@ -2347,7 +2427,12 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2347
2427
|
}, t(provider === "github" ? "githubLogin" : "zhihuLogin")), selectHost = async (host) => {
|
|
2348
2428
|
setBusy(!0), setError(void 0);
|
|
2349
2429
|
try {
|
|
2350
|
-
setWorkspaces(await
|
|
2430
|
+
setWorkspaces(await runRemoteProgress(
|
|
2431
|
+
connectHostProgressSteps,
|
|
2432
|
+
setProgress,
|
|
2433
|
+
progressRun,
|
|
2434
|
+
() => props.control("workspaces.list", { targetDeviceId: host.deviceId })
|
|
2435
|
+
)), setSelectedHost(host), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
2351
2436
|
} catch (reason) {
|
|
2352
2437
|
setError(messageOf(reason));
|
|
2353
2438
|
} finally {
|
|
@@ -2423,10 +2508,15 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2423
2508
|
if (!(selectedHost === void 0 || path.trim() === "")) {
|
|
2424
2509
|
setBusy(!0), setError(void 0);
|
|
2425
2510
|
try {
|
|
2426
|
-
await
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2511
|
+
await runRemoteProgress(
|
|
2512
|
+
openWorkspaceProgressSteps,
|
|
2513
|
+
setProgress,
|
|
2514
|
+
progressRun,
|
|
2515
|
+
() => props.control("workspace.open", {
|
|
2516
|
+
targetDeviceId: selectedHost.deviceId,
|
|
2517
|
+
path: path.trim()
|
|
2518
|
+
})
|
|
2519
|
+
), window.location.reload();
|
|
2430
2520
|
} catch (reason) {
|
|
2431
2521
|
setError(messageOf(reason)), setBusy(!1);
|
|
2432
2522
|
}
|
|
@@ -2663,6 +2753,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2663
2753
|
React.createElement("small", null, [formatPlatform(selectedHost.platform), t("online")].join(" \xB7 "))
|
|
2664
2754
|
)
|
|
2665
2755
|
),
|
|
2756
|
+
React.createElement(RemoteProgressView, { progress, t }),
|
|
2666
2757
|
selectedHost === void 0 ? React.createElement("p", { className: "dshRemoteHint" }, t("selectHostHint")) : React.createElement(
|
|
2667
2758
|
"section",
|
|
2668
2759
|
{ className: "dshRemoteBrowser", "aria-label": t("chooseDirectory") },
|
|
@@ -2742,7 +2833,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2742
2833
|
);
|
|
2743
2834
|
}
|
|
2744
2835
|
function RemoteModeAction(props) {
|
|
2745
|
-
let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [hostRegistrationCode, setHostRegistrationCode] = React.useState(""), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [busy, setBusy] = React.useState(!1), [error, setError] = React.useState(void 0), [supported, setSupported] = React.useState(!0), refresh = async () => {
|
|
2836
|
+
let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [hostRegistrationCode, setHostRegistrationCode] = React.useState(""), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [busy, setBusy] = React.useState(!1), [progress, setProgress] = React.useState(void 0), progressRun = React.useRef(0), [error, setError] = React.useState(void 0), [supported, setSupported] = React.useState(!0), refresh = async () => {
|
|
2746
2837
|
let [nextStatus, nextDevices] = await Promise.all([
|
|
2747
2838
|
props.control("status"),
|
|
2748
2839
|
props.control("devices").catch(() => [])
|
|
@@ -2766,7 +2857,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2766
2857
|
let switchMode = async (mode, targetDeviceId) => {
|
|
2767
2858
|
setBusy(!0), setError(void 0);
|
|
2768
2859
|
try {
|
|
2769
|
-
|
|
2860
|
+
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();
|
|
2770
2862
|
} catch (reason) {
|
|
2771
2863
|
setError(messageOf(reason)), setBusy(!1);
|
|
2772
2864
|
}
|
|
@@ -2831,6 +2923,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2831
2923
|
disabled: busy || !device.online || status?.target?.deviceId === device.deviceId,
|
|
2832
2924
|
onClick: () => void switchMode("remote", device.deviceId)
|
|
2833
2925
|
}, `${device.name} \xB7 ${t(device.online ? "online" : "offline")}`))),
|
|
2926
|
+
React.createElement(RemoteProgressView, { progress, t }),
|
|
2834
2927
|
status?.hostAuthorizationAvailable && status.host !== void 0 ? React.createElement(
|
|
2835
2928
|
"div",
|
|
2836
2929
|
{ className: "dshRemoteHostAccount" },
|
|
@@ -3076,6 +3169,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3076
3169
|
".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)}",
|
|
3077
3170
|
".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}",
|
|
3078
3171
|
".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}}",
|
|
3079
3173
|
'.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}',
|
|
3080
3174
|
".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}",
|
|
3081
3175
|
".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)}",
|
package/dist/client.js
CHANGED
|
@@ -1771,6 +1771,20 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
1771
1771
|
openWorkspace: "Open workspace",
|
|
1772
1772
|
openingWorkspace: "Opening\u2026",
|
|
1773
1773
|
loadingDirectory: "Loading directories\u2026",
|
|
1774
|
+
remoteProgressCheckingHost: "Checking Host",
|
|
1775
|
+
remoteProgressCheckingHostDetail: "Finding the selected device and checking whether it is online.",
|
|
1776
|
+
remoteProgressAuthorizingPeer: "Verifying authorization",
|
|
1777
|
+
remoteProgressAuthorizingPeerDetail: "Confirming account membership and pinned Host identity.",
|
|
1778
|
+
remoteProgressOpeningChannel: "Opening encrypted channel",
|
|
1779
|
+
remoteProgressOpeningChannelDetail: "Trying LAN, P2P, TURN, then Relay if needed.",
|
|
1780
|
+
remoteProgressLoadingWorkspaces: "Loading workspaces",
|
|
1781
|
+
remoteProgressLoadingWorkspacesDetail: "Reading the remote Harness workspace list through the tunnel.",
|
|
1782
|
+
remoteProgressOpeningWorkspace: "Opening workspace",
|
|
1783
|
+
remoteProgressOpeningWorkspaceDetail: "Asking the Host to prepare the selected working directory.",
|
|
1784
|
+
remoteProgressSwitchingWorkspace: "Switching interface",
|
|
1785
|
+
remoteProgressSwitchingWorkspaceDetail: "Handing the remote workspace to the local Harness UI.",
|
|
1786
|
+
remoteProgressReady: "Ready",
|
|
1787
|
+
remoteProgressReadyDetail: "The remote Host is connected and encrypted.",
|
|
1774
1788
|
backToHosts: "Choose another Host",
|
|
1775
1789
|
currentDirectory: "Selected directory",
|
|
1776
1790
|
directoryTruncated: "Only part of this directory could be shown.",
|
|
@@ -1941,6 +1955,20 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
1941
1955
|
openWorkspace: "\u6253\u5F00\u5DE5\u4F5C\u533A",
|
|
1942
1956
|
openingWorkspace: "\u6B63\u5728\u6253\u5F00\u2026",
|
|
1943
1957
|
loadingDirectory: "\u6B63\u5728\u52A0\u8F7D\u76EE\u5F55\u2026",
|
|
1958
|
+
remoteProgressCheckingHost: "\u6B63\u5728\u68C0\u67E5 Host",
|
|
1959
|
+
remoteProgressCheckingHostDetail: "\u6B63\u5728\u67E5\u627E\u6240\u9009\u8BBE\u5907\u5E76\u786E\u8BA4\u662F\u5426\u5728\u7EBF\u3002",
|
|
1960
|
+
remoteProgressAuthorizingPeer: "\u6B63\u5728\u9A8C\u8BC1\u6388\u6743",
|
|
1961
|
+
remoteProgressAuthorizingPeerDetail: "\u6B63\u5728\u786E\u8BA4\u8D26\u53F7\u6210\u5458\u5173\u7CFB\u548C\u5DF2\u56FA\u5B9A\u7684 Host \u8EAB\u4EFD\u3002",
|
|
1962
|
+
remoteProgressOpeningChannel: "\u6B63\u5728\u5EFA\u7ACB\u52A0\u5BC6\u901A\u9053",
|
|
1963
|
+
remoteProgressOpeningChannelDetail: "\u4F9D\u6B21\u5C1D\u8BD5\u5C40\u57DF\u7F51\u3001P2P\u3001TURN\uFF0C\u5FC5\u8981\u65F6\u56DE\u843D\u5230 Relay\u3002",
|
|
1964
|
+
remoteProgressLoadingWorkspaces: "\u6B63\u5728\u52A0\u8F7D\u5DE5\u4F5C\u533A",
|
|
1965
|
+
remoteProgressLoadingWorkspacesDetail: "\u901A\u8FC7\u96A7\u9053\u8BFB\u53D6\u8FDC\u7AEF Harness \u5DE5\u4F5C\u533A\u5217\u8868\u3002",
|
|
1966
|
+
remoteProgressOpeningWorkspace: "\u6B63\u5728\u6253\u5F00\u5DE5\u4F5C\u533A",
|
|
1967
|
+
remoteProgressOpeningWorkspaceDetail: "\u6B63\u5728\u8BF7\u6C42 Host \u51C6\u5907\u6240\u9009\u5DE5\u4F5C\u76EE\u5F55\u3002",
|
|
1968
|
+
remoteProgressSwitchingWorkspace: "\u6B63\u5728\u5207\u6362\u754C\u9762",
|
|
1969
|
+
remoteProgressSwitchingWorkspaceDetail: "\u6B63\u5728\u628A\u8FDC\u7AEF\u5DE5\u4F5C\u533A\u4EA4\u7ED9\u672C\u5730 Harness UI\u3002",
|
|
1970
|
+
remoteProgressReady: "\u5DF2\u5C31\u7EEA",
|
|
1971
|
+
remoteProgressReadyDetail: "\u8FDC\u7AEF Host \u5DF2\u8FDE\u63A5\uFF0C\u7AEF\u5230\u7AEF\u52A0\u5BC6\u5DF2\u5EFA\u7ACB\u3002",
|
|
1944
1972
|
backToHosts: "\u9009\u62E9\u5176\u4ED6\u4E3B\u673A",
|
|
1945
1973
|
currentDirectory: "\u5DF2\u9009\u76EE\u5F55",
|
|
1946
1974
|
directoryTruncated: "\u76EE\u5F55\u5185\u5BB9\u8F83\u591A\uFF0C\u76EE\u524D\u53EA\u663E\u793A\u4E86\u4E00\u90E8\u5206\u3002",
|
|
@@ -2054,6 +2082,58 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2054
2082
|
id: clientModuleId,
|
|
2055
2083
|
factory: (require2) => {
|
|
2056
2084
|
let module = { exports: {} }, React = require2("react"), inject = ["connection", "slots", "locale", "workspaces", "sessions"];
|
|
2085
|
+
function RemoteProgressView(props) {
|
|
2086
|
+
let progress = props.progress;
|
|
2087
|
+
if (progress === void 0) return null;
|
|
2088
|
+
let percent = Math.max(0, Math.min(100, Math.round(progress.percent)));
|
|
2089
|
+
return React.createElement(
|
|
2090
|
+
"div",
|
|
2091
|
+
{
|
|
2092
|
+
className: "dshRemoteProgress",
|
|
2093
|
+
role: "status",
|
|
2094
|
+
"aria-live": "polite"
|
|
2095
|
+
},
|
|
2096
|
+
React.createElement(
|
|
2097
|
+
"div",
|
|
2098
|
+
{ className: "dshRemoteProgressHeader" },
|
|
2099
|
+
React.createElement("strong", null, props.t(progress.label)),
|
|
2100
|
+
React.createElement("span", null, `${percent}%`)
|
|
2101
|
+
),
|
|
2102
|
+
React.createElement("div", {
|
|
2103
|
+
className: "dshRemoteProgressBar",
|
|
2104
|
+
role: "progressbar",
|
|
2105
|
+
"aria-valuemin": 0,
|
|
2106
|
+
"aria-valuemax": 100,
|
|
2107
|
+
"aria-valuenow": percent,
|
|
2108
|
+
"aria-label": props.t(progress.label)
|
|
2109
|
+
}, React.createElement("span", { style: { width: `${percent}%` } })),
|
|
2110
|
+
React.createElement("p", null, props.t(progress.detail))
|
|
2111
|
+
);
|
|
2112
|
+
}
|
|
2113
|
+
async function runRemoteProgress(steps, setProgress, progressRun, action) {
|
|
2114
|
+
let runId = progressRun.current + 1;
|
|
2115
|
+
progressRun.current = runId;
|
|
2116
|
+
let apply2 = (next) => {
|
|
2117
|
+
progressRun.current === runId && setProgress(next);
|
|
2118
|
+
}, [first, ...rest] = steps;
|
|
2119
|
+
first !== void 0 && apply2(first);
|
|
2120
|
+
let timers = rest.map((step) => window.setTimeout(() => apply2(step), step.delayMs ?? 0));
|
|
2121
|
+
try {
|
|
2122
|
+
let result = await action();
|
|
2123
|
+
return apply2({ label: "remoteProgressReady", detail: "remoteProgressReadyDetail", percent: 100 }), await new Promise((resolve) => window.setTimeout(resolve, 220)), result;
|
|
2124
|
+
} finally {
|
|
2125
|
+
timers.forEach((timer) => window.clearTimeout(timer)), progressRun.current === runId && setProgress(void 0);
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
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 = [
|
|
2134
|
+
{ label: "remoteProgressOpeningWorkspace", detail: "remoteProgressOpeningWorkspaceDetail", percent: 30 },
|
|
2135
|
+
{ label: "remoteProgressSwitchingWorkspace", detail: "remoteProgressSwitchingWorkspaceDetail", percent: 74, delayMs: 520 }
|
|
2136
|
+
];
|
|
2057
2137
|
function RemotePluginOptions(props) {
|
|
2058
2138
|
let { t } = props, [open, setOpen] = React.useState(!1), [serverUrl, setServerUrl] = React.useState(""), role = "host", [registrationCode, setRegistrationCode] = React.useState(""), [associations, setAssociations] = React.useState({}), [loaded, setLoaded] = React.useState(!1), [writable, setWritable] = React.useState(!1), [busy, setBusy] = React.useState(!1), [reconnectBusy, setReconnectBusy] = React.useState(!1), [hostStatus, setHostStatus] = React.useState(void 0), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0), [settingsView, setSettingsView] = React.useState(void 0), persistedServerUrl = settingsView?.config.serverUrl ?? "https://dsh.r2049.cn", association = associations.client ?? associations.host, serverDirty = settingsView !== void 0 && serverUrl !== persistedServerUrl, draftDirty = serverDirty, applyView = (view) => {
|
|
2059
2139
|
setSettingsView(view), setServerUrl(view.config.serverUrl ?? "https://dsh.r2049.cn"), setAssociations(view.associations ?? (view.association === void 0 ? {} : { host: view.association })), setWritable(view.writable), setLoaded(!0);
|
|
@@ -2282,7 +2362,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2282
2362
|
);
|
|
2283
2363
|
}
|
|
2284
2364
|
function RemoteWorkspaceAction(props) {
|
|
2285
|
-
let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [selectedHost, setSelectedHost] = React.useState(void 0), [workspaces, setWorkspaces] = React.useState([]), [directory, setDirectory] = React.useState(void 0), [path, setPath] = React.useState(""), [addingWorkspace, setAddingWorkspace] = React.useState(!1), [busy, setBusy] = React.useState(!1), [needsAuthorization, setNeedsAuthorization] = React.useState(!1), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [loginMethod, setLoginMethod] = React.useState(props.preferredQrProvider), [loginMethodManuallySelected, setLoginMethodManuallySelected] = React.useState(!1), [qrSession, setQrSession] = React.useState(void 0), [qrImage, setQrImage] = React.useState(void 0), [qrExpired, setQrExpired] = React.useState(!1), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0);
|
|
2365
|
+
let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [selectedHost, setSelectedHost] = React.useState(void 0), [workspaces, setWorkspaces] = React.useState([]), [directory, setDirectory] = React.useState(void 0), [path, setPath] = React.useState(""), [addingWorkspace, setAddingWorkspace] = React.useState(!1), [busy, setBusy] = React.useState(!1), [needsAuthorization, setNeedsAuthorization] = React.useState(!1), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [loginMethod, setLoginMethod] = React.useState(props.preferredQrProvider), [loginMethodManuallySelected, setLoginMethodManuallySelected] = React.useState(!1), [qrSession, setQrSession] = React.useState(void 0), [qrImage, setQrImage] = React.useState(void 0), [qrExpired, setQrExpired] = React.useState(!1), [progress, setProgress] = React.useState(void 0), progressRun = React.useRef(0), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0);
|
|
2286
2366
|
React.useEffect(() => {
|
|
2287
2367
|
if (!open) return;
|
|
2288
2368
|
let closeOnEscape = (event) => {
|
|
@@ -2347,7 +2427,12 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2347
2427
|
}, t(provider === "github" ? "githubLogin" : "zhihuLogin")), selectHost = async (host) => {
|
|
2348
2428
|
setBusy(!0), setError(void 0);
|
|
2349
2429
|
try {
|
|
2350
|
-
setWorkspaces(await
|
|
2430
|
+
setWorkspaces(await runRemoteProgress(
|
|
2431
|
+
connectHostProgressSteps,
|
|
2432
|
+
setProgress,
|
|
2433
|
+
progressRun,
|
|
2434
|
+
() => props.control("workspaces.list", { targetDeviceId: host.deviceId })
|
|
2435
|
+
)), setSelectedHost(host), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
2351
2436
|
} catch (reason) {
|
|
2352
2437
|
setError(messageOf(reason));
|
|
2353
2438
|
} finally {
|
|
@@ -2423,10 +2508,15 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2423
2508
|
if (!(selectedHost === void 0 || path.trim() === "")) {
|
|
2424
2509
|
setBusy(!0), setError(void 0);
|
|
2425
2510
|
try {
|
|
2426
|
-
await
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2511
|
+
await runRemoteProgress(
|
|
2512
|
+
openWorkspaceProgressSteps,
|
|
2513
|
+
setProgress,
|
|
2514
|
+
progressRun,
|
|
2515
|
+
() => props.control("workspace.open", {
|
|
2516
|
+
targetDeviceId: selectedHost.deviceId,
|
|
2517
|
+
path: path.trim()
|
|
2518
|
+
})
|
|
2519
|
+
), window.location.reload();
|
|
2430
2520
|
} catch (reason) {
|
|
2431
2521
|
setError(messageOf(reason)), setBusy(!1);
|
|
2432
2522
|
}
|
|
@@ -2663,6 +2753,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2663
2753
|
React.createElement("small", null, [formatPlatform(selectedHost.platform), t("online")].join(" \xB7 "))
|
|
2664
2754
|
)
|
|
2665
2755
|
),
|
|
2756
|
+
React.createElement(RemoteProgressView, { progress, t }),
|
|
2666
2757
|
selectedHost === void 0 ? React.createElement("p", { className: "dshRemoteHint" }, t("selectHostHint")) : React.createElement(
|
|
2667
2758
|
"section",
|
|
2668
2759
|
{ className: "dshRemoteBrowser", "aria-label": t("chooseDirectory") },
|
|
@@ -2742,7 +2833,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2742
2833
|
);
|
|
2743
2834
|
}
|
|
2744
2835
|
function RemoteModeAction(props) {
|
|
2745
|
-
let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [hostRegistrationCode, setHostRegistrationCode] = React.useState(""), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [busy, setBusy] = React.useState(!1), [error, setError] = React.useState(void 0), [supported, setSupported] = React.useState(!0), refresh = async () => {
|
|
2836
|
+
let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [hostRegistrationCode, setHostRegistrationCode] = React.useState(""), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [busy, setBusy] = React.useState(!1), [progress, setProgress] = React.useState(void 0), progressRun = React.useRef(0), [error, setError] = React.useState(void 0), [supported, setSupported] = React.useState(!0), refresh = async () => {
|
|
2746
2837
|
let [nextStatus, nextDevices] = await Promise.all([
|
|
2747
2838
|
props.control("status"),
|
|
2748
2839
|
props.control("devices").catch(() => [])
|
|
@@ -2766,7 +2857,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2766
2857
|
let switchMode = async (mode, targetDeviceId) => {
|
|
2767
2858
|
setBusy(!0), setError(void 0);
|
|
2768
2859
|
try {
|
|
2769
|
-
|
|
2860
|
+
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();
|
|
2770
2862
|
} catch (reason) {
|
|
2771
2863
|
setError(messageOf(reason)), setBusy(!1);
|
|
2772
2864
|
}
|
|
@@ -2831,6 +2923,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2831
2923
|
disabled: busy || !device.online || status?.target?.deviceId === device.deviceId,
|
|
2832
2924
|
onClick: () => void switchMode("remote", device.deviceId)
|
|
2833
2925
|
}, `${device.name} \xB7 ${t(device.online ? "online" : "offline")}`))),
|
|
2926
|
+
React.createElement(RemoteProgressView, { progress, t }),
|
|
2834
2927
|
status?.hostAuthorizationAvailable && status.host !== void 0 ? React.createElement(
|
|
2835
2928
|
"div",
|
|
2836
2929
|
{ className: "dshRemoteHostAccount" },
|
|
@@ -3076,6 +3169,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3076
3169
|
".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)}",
|
|
3077
3170
|
".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}",
|
|
3078
3171
|
".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}}",
|
|
3079
3173
|
'.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}',
|
|
3080
3174
|
".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}",
|
|
3081
3175
|
".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)}",
|