@linxin666/dsh-remote-web-ui 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +9 -7
- package/README.zh.md +9 -7
- package/lib/client.js +282 -619
- package/lib/client.js.map +1 -1
- package/lib/index.js +418 -901
- package/lib/types/client/RemoteEntry.d.ts.map +1 -1
- package/lib/types/client/RemoteEntry.js +9 -10
- package/lib/types/client/RemoteSettingsCard.d.ts.map +1 -1
- package/lib/types/client/RemoteSettingsCard.js +1 -1
- package/lib/types/client/index.d.ts +32 -3
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +56 -11
- package/lib/types/client/locales.d.ts +0 -84
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/locales.js +2 -86
- package/lib/types/client/pair-api.d.ts +4 -0
- package/lib/types/client/pair-api.d.ts.map +1 -1
- package/lib/types/client/pair-api.js +11 -7
- package/lib/types/client/remote-channel.d.ts +27 -7
- package/lib/types/client/remote-channel.d.ts.map +1 -1
- package/lib/types/client/remote-channel.js +25 -17
- package/lib/types/client/settings-entry-form.d.ts +50 -0
- package/lib/types/client/settings-entry-form.d.ts.map +1 -0
- package/lib/types/client/settings-entry-form.js +98 -0
- package/lib/types/index.d.ts +99 -7
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +104 -137
- package/lib/types/lan-bind-plan.d.ts +14 -0
- package/lib/types/lan-bind-plan.d.ts.map +1 -1
- package/lib/types/lan-bind-plan.js +16 -0
- package/lib/types/lan-bind.d.ts +5 -1
- package/lib/types/lan-bind.d.ts.map +1 -1
- package/lib/types/lan-bind.js +65 -2
- package/lib/types/mount-once.d.ts +38 -7
- package/lib/types/mount-once.d.ts.map +1 -1
- package/lib/types/mount-once.js +96 -12
- package/lib/types/pairing.d.ts +15 -2
- package/lib/types/pairing.d.ts.map +1 -1
- package/lib/types/pairing.js +26 -14
- package/lib/types/pairing.persist.test.js +43 -3
- package/lib/types/remote-channel-boot.d.ts.map +1 -1
- package/lib/types/remote-channel-boot.js +13 -3
- package/lib/types/remote-channel-rules.d.ts +74 -0
- package/lib/types/remote-channel-rules.d.ts.map +1 -1
- package/lib/types/remote-channel-rules.js +104 -0
- package/lib/types/tunnel.d.ts +60 -3
- package/lib/types/tunnel.d.ts.map +1 -1
- package/lib/types/tunnel.js +136 -3
- package/package.json +21 -20
- package/src/client/RemoteEntry.tsx +8 -10
- package/src/client/RemoteSettingsCard.tsx +0 -2
- package/src/client/index.ts +58 -12
- package/src/client/locales.ts +2 -86
- package/src/client/pair-api.ts +11 -7
- package/src/client/remote-channel.ts +38 -15
- package/src/client/remote.module.css +61 -193
- package/src/client/settings-entry-form.ts +142 -0
- package/src/index.ts +156 -152
- package/src/lan-bind-plan.ts +22 -0
- package/src/lan-bind.ts +63 -2
- package/src/mount-once.ts +107 -13
- package/src/pairing.persist.test.ts +47 -3
- package/src/pairing.ts +26 -12
- package/src/remote-channel-boot.ts +13 -3
- package/src/remote-channel-rules.ts +113 -0
- package/src/tunnel.ts +142 -3
- package/lib/types/client/UpdateEntry.d.ts +0 -14
- package/lib/types/client/UpdateEntry.d.ts.map +0 -1
- package/lib/types/client/UpdateEntry.js +0 -112
- package/lib/types/client/UpdatePanel.d.ts +0 -42
- package/lib/types/client/UpdatePanel.d.ts.map +0 -1
- package/lib/types/client/UpdatePanel.js +0 -101
- package/lib/types/client/update-api.d.ts +0 -29
- package/lib/types/client/update-api.d.ts.map +0 -1
- package/lib/types/client/update-api.js +0 -47
- package/lib/types/console-output.d.ts +0 -41
- package/lib/types/console-output.d.ts.map +0 -1
- package/lib/types/console-output.js +0 -89
- package/lib/types/update-routes.d.ts +0 -30
- package/lib/types/update-routes.d.ts.map +0 -1
- package/lib/types/update-routes.js +0 -47
- package/lib/types/update.d.ts +0 -272
- package/lib/types/update.d.ts.map +0 -1
- package/lib/types/update.js +0 -744
- package/src/client/UpdateEntry.tsx +0 -144
- package/src/client/UpdatePanel.tsx +0 -256
- package/src/client/update-api.ts +0 -49
- package/src/console-output.ts +0 -97
- package/src/update-routes.ts +0 -65
- package/src/update.ts +0 -882
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoteEntry.d.ts","sourceRoot":"","sources":["../../../src/client/RemoteEntry.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;
|
|
1
|
+
{"version":3,"file":"RemoteEntry.d.ts","sourceRoot":"","sources":["../../../src/client/RemoteEntry.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAOnE,0EAA0E;AAC1E,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC,QAAQ,CAAC,GAAG;IACrD,oEAAoE;IACpE,IAAI,EAAE,OAAO,CAAA;CACd,CAAA;AA2BD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,gBAAgB,+BA2MxD"}
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
|
-
* The sidebar remote-control seat: the
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
3
|
+
* The sidebar remote-control seat: the phone-icon trigger beside the
|
|
4
|
+
* settings button, and the pairing panel modal. Owns the panel behavior —
|
|
5
|
+
* token minting on open, the status SSE subscription, stop/refresh/copy — and
|
|
6
|
+
* renders the pure {@link RemotePanel} body. The family self-update seat is
|
|
7
|
+
* its own plugin (dsh-update) and no longer rides this row. Component-local
|
|
8
|
+
* state per the client stack rules: nothing here survives remounts or crosses
|
|
9
|
+
* entries.
|
|
10
10
|
*/
|
|
11
11
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
12
12
|
import { createPortal } from 'react-dom';
|
|
13
13
|
import { RemotePanel } from "./RemotePanel.js";
|
|
14
14
|
import { copyText, issuePair, revokePair, stopPair } from "./pair-api.js";
|
|
15
15
|
import { PhoneIcon } from "./PhoneIcon.js";
|
|
16
|
-
import { UpdateEntry } from "./UpdateEntry.js";
|
|
17
16
|
import css from './remote.module.css';
|
|
18
17
|
/**
|
|
19
18
|
* Apply one status frame onto the current state: the ready state mirrors
|
|
@@ -122,7 +121,7 @@ export function RemoteEntry({ wide, t }) {
|
|
|
122
121
|
// it there would just start a doomed reconnect loop.
|
|
123
122
|
if (next.kind !== 'ready' && next.kind !== 'lan-required')
|
|
124
123
|
return;
|
|
125
|
-
const source = new EventSource('
|
|
124
|
+
const source = new EventSource('api/pair/events');
|
|
126
125
|
eventSource.current = source;
|
|
127
126
|
source.onmessage = (event) => {
|
|
128
127
|
try {
|
|
@@ -217,7 +216,7 @@ export function RemoteEntry({ wide, t }) {
|
|
|
217
216
|
window.setTimeout(() => { setCopiedToken(false); }, 1500);
|
|
218
217
|
});
|
|
219
218
|
}, []);
|
|
220
|
-
return (_jsxs(_Fragment, { children: [
|
|
219
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: css.entryRow, "data-rail": wide ? undefined : 'rail', children: _jsx(TooltipAnchor, { wide: wide, label: t('entry.label'), onClick: openPanel, expanded: open }) }), open && createPortal((_jsxs("div", { className: css.overlay, role: "presentation", children: [_jsx("div", { className: css.mask, "aria-hidden": "true", onClick: closePanel }), _jsx(RemotePanel, { t: t, state: state, copied: copied, copiedToken: copiedToken, onClose: closePanel, onStop: handleStop, onRefresh: handleRefresh, onCopy: handleCopy, onCopyToken: handleCopyToken, onPickAddress: handlePickAddress, onPickPublic: handlePickPublic, onRevoke: handleRevoke })] })), document.body)] }));
|
|
221
220
|
}
|
|
222
221
|
/** The trigger: an icon-only control with a persistent accessible label. */
|
|
223
222
|
function TooltipAnchor({ wide, label, onClick, expanded }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoteSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/client/RemoteSettingsCard.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAC7F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4CAA4C,CAAA;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAElE,OAAO,EAA+D,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAIrK,+EAA+E;AAC/E,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,6FAA6F;IAC7F,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,4CAA4C;AAC5C,MAAM,WAAW,uBAAwB,SAAQ,SAAS;IACxD,qBAAqB;IACrB,OAAO,EAAE,cAAc,CAAA;IACvB,sBAAsB;IACtB,UAAU,EAAE,cAAc,CAAA;IAC1B,gCAAgC;IAChC,cAAc,EAAE,cAAc,CAAA;IAC9B,yBAAyB;IACzB,UAAU,EAAE,cAAc,CAAA;IAC1B,0BAA0B;IAC1B,YAAY,EAAE,cAAc,CAAA;IAC5B,0BAA0B;IAC1B,UAAU,EAAE,cAAc,CAAA;IAC1B,sBAAsB;IACtB,oBAAoB,EAAE,cAAc,CAAA;IACpC,kCAAkC;IAClC,aAAa,EAAE,cAAc,CAAA;IAC7B,iCAAiC;IACjC,UAAU,EAAE,cAAc,CAAA;IAC1B,wDAAwD;IACxD,WAAW,EAAE,cAAc,CAAA;IAC3B,kCAAkC;IAClC,KAAK,EAAE,cAAc,CAAA;IACrB,uBAAuB;IACvB,OAAO,EAAE,cAAc,CAAA;CACxB;AAED,gEAAgE;AAChE,MAAM,WAAW,sBAAuB,SAAQ,WAAW;IACzD,KAAK,EAAE;QACL,oEAAoE;QACpE,kBAAkB,EAAE,aAAa,CAAC,uBAAuB,CAAC,CAAA;KAC3D,CAAA;CACF;AAED,oEAAoE;AACpE,qBAAa,4BAA4B;IACvC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwC;IAE9D,2EAA2E;gBAC/D,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC;IAkB7C,OAAO,CAAC,UAAU;IAkBlB;;;OAGG;IACH,MAAM,IAAI,sBAAsB;IAIhC;;;OAGG;IACH,OAAO,IAAI,IAAI;CAGhB;AAED,4DAA4D;AAC5D,MAAM,MAAM,uBAAuB,GACjC,YAAY,CAAC,oBAAoB,CAAC,GAChC,WAAW,CAAC,QAAQ,CAAC,GACrB,UAAU,CAAC,sBAAsB,CAAC,CAAA;AAEtC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,+
|
|
1
|
+
{"version":3,"file":"RemoteSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/client/RemoteSettingsCard.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAC7F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4CAA4C,CAAA;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAElE,OAAO,EAA+D,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAIrK,+EAA+E;AAC/E,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,6FAA6F;IAC7F,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,4CAA4C;AAC5C,MAAM,WAAW,uBAAwB,SAAQ,SAAS;IACxD,qBAAqB;IACrB,OAAO,EAAE,cAAc,CAAA;IACvB,sBAAsB;IACtB,UAAU,EAAE,cAAc,CAAA;IAC1B,gCAAgC;IAChC,cAAc,EAAE,cAAc,CAAA;IAC9B,yBAAyB;IACzB,UAAU,EAAE,cAAc,CAAA;IAC1B,0BAA0B;IAC1B,YAAY,EAAE,cAAc,CAAA;IAC5B,0BAA0B;IAC1B,UAAU,EAAE,cAAc,CAAA;IAC1B,sBAAsB;IACtB,oBAAoB,EAAE,cAAc,CAAA;IACpC,kCAAkC;IAClC,aAAa,EAAE,cAAc,CAAA;IAC7B,iCAAiC;IACjC,UAAU,EAAE,cAAc,CAAA;IAC1B,wDAAwD;IACxD,WAAW,EAAE,cAAc,CAAA;IAC3B,kCAAkC;IAClC,KAAK,EAAE,cAAc,CAAA;IACrB,uBAAuB;IACvB,OAAO,EAAE,cAAc,CAAA;CACxB;AAED,gEAAgE;AAChE,MAAM,WAAW,sBAAuB,SAAQ,WAAW;IACzD,KAAK,EAAE;QACL,oEAAoE;QACpE,kBAAkB,EAAE,aAAa,CAAC,uBAAuB,CAAC,CAAA;KAC3D,CAAA;CACF;AAED,oEAAoE;AACpE,qBAAa,4BAA4B;IACvC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwC;IAE9D,2EAA2E;gBAC/D,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC;IAkB7C,OAAO,CAAC,UAAU;IAkBlB;;;OAGG;IACH,MAAM,IAAI,sBAAsB;IAIhC;;;OAGG;IACH,OAAO,IAAI,IAAI;CAGhB;AAED,4DAA4D;AAC5D,MAAM,MAAM,uBAAuB,GACjC,YAAY,CAAC,oBAAoB,CAAC,GAChC,WAAW,CAAC,QAAQ,CAAC,GACrB,UAAU,CAAC,sBAAsB,CAAC,CAAA;AAEtC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,+BAwJhE"}
|
|
@@ -77,7 +77,7 @@ export function RemoteSettingsCard(props) {
|
|
|
77
77
|
invalidLabel: t('settings.invalidNumber'),
|
|
78
78
|
disabled,
|
|
79
79
|
};
|
|
80
|
-
return (_jsxs(PluginSettingsCard, { t: t, titleKey: "settings.title", descriptionKey: "settings.description", defaultOpen: false, state: state,
|
|
80
|
+
return (_jsxs(PluginSettingsCard, { t: t, titleKey: "settings.title", descriptionKey: "settings.description", defaultOpen: false, state: state, onSave: props.save, onDiscard: props.discard, children: [_jsx(BooleanField, { id: "settings-remote-enabled", label: t('settings.enabled'), hint: t('settings.enabledHint'), inheritLabel: t('settings.inherit'), onLabel: t('settings.on'), offLabel: t('settings.off'), ...fieldProps, ...state.enabled, onEdit: (text) => { props.edit('enabled', text); }, onReset: () => { props.resetField('enabled'); } }), _jsx(ValueField, { id: "settings-remote-token-ttl", label: t('settings.tokenTtlMs'), hint: t('settings.tokenTtlMsHint'), numeric: true, ...fieldProps, ...state.tokenTtlMs, onEdit: (text) => { props.edit('tokenTtlMs', text); }, onReset: () => { props.resetField('tokenTtlMs'); } }), _jsx(ValueField, { id: "settings-remote-offline", label: t('settings.offlineAfterMs'), hint: t('settings.offlineAfterMsHint'), numeric: true, ...fieldProps, ...state.offlineAfterMs, onEdit: (text) => { props.edit('offlineAfterMs', text); }, onReset: () => { props.resetField('offlineAfterMs'); } }), _jsx(ValueField, { id: "settings-remote-max-devices", label: t('settings.maxDevices'), hint: t('settings.maxDevicesHint'), numeric: true, ...fieldProps, ...state.maxDevices, onEdit: (text) => { props.edit('maxDevices', text); }, onReset: () => { props.resetField('maxDevices'); } }), _jsx(ValueField, { id: "settings-remote-idle-expire", label: t('settings.idleExpireMs'), hint: t('settings.idleExpireMsHint'), numeric: true, ...fieldProps, ...state.idleExpireMs, onEdit: (text) => { props.edit('idleExpireMs', text); }, onReset: () => { props.resetField('idleExpireMs'); } }), _jsx(ValueField, { id: "settings-remote-cookie", label: t('settings.cookieName'), hint: t('settings.cookieNameHint'), ...fieldProps, ...state.cookieName, onEdit: (text) => { props.edit('cookieName', text); }, onReset: () => { props.resetField('cookieName'); } }), _jsx(BooleanField, { id: "settings-remote-fence", label: t('settings.requirePairingForLan'), hint: t('settings.requirePairingForLanHint'), inheritLabel: t('settings.inherit'), onLabel: t('settings.on'), offLabel: t('settings.off'), ...fieldProps, ...state.requirePairingForLan, onEdit: (text) => { props.edit('requirePairingForLan', text); }, onReset: () => { props.resetField('requirePairingForLan'); } }), _jsx(ValueField, { id: "settings-remote-public-base", label: t('settings.publicBaseUrl'), hint: t('settings.publicBaseUrlHint'), placeholder: "https://example.trycloudflare.com", ...fieldProps, ...state.publicBaseUrl, onEdit: (text) => { props.edit('publicBaseUrl', text); }, onReset: () => { props.resetField('publicBaseUrl'); } }), _jsx(BooleanField, { id: "settings-remote-auto-tunnel", label: t('settings.autoTunnel'), hint: t('settings.autoTunnelHint'), inheritLabel: t('settings.inherit'), onLabel: t('settings.on'), offLabel: t('settings.off'), ...fieldProps, ...state.autoTunnel, onEdit: (text) => { props.edit('autoTunnel', text); }, onReset: () => { props.resetField('autoTunnel'); } }), _jsx(ValueField, { id: "settings-remote-tunnel-token", label: t('settings.tunnelToken'), hint: t('settings.tunnelTokenHint'), placeholder: "eyJ...", ...fieldProps, ...state.tunnelToken, onEdit: (text) => { props.edit('tunnelToken', text); }, onReset: () => { props.resetField('tunnelToken'); } }), _jsx(BooleanField, { id: "settings-remote-relay", label: t('settings.relay'), hint: t('settings.relayHint'), inheritLabel: t('settings.inherit'), onLabel: t('settings.on'), offLabel: t('settings.off'), ...fieldProps, ...state.relay, onEdit: (text) => { props.edit('relay', text); }, onReset: () => { props.resetField('relay'); } }), _jsx(LanBindStatus, { t: t }), _jsx(BooleanField, { id: "settings-remote-lan-bind", label: t('settings.lanBind'), hint: t('settings.lanBindHint'), inheritLabel: t('settings.inherit'), onLabel: t('settings.on'), offLabel: t('settings.off'), ...fieldProps, ...state.lanBind, onEdit: (text) => { props.edit('lanBind', text); }, onReset: () => { props.resetField('lanBind'); } })] }));
|
|
81
81
|
}
|
|
82
82
|
/**
|
|
83
83
|
* Live LAN-bind facts above the toggle: the managed block's host, the live
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
2
|
-
import type { ConfigForm } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
2
|
+
import type { ConfigForm, ConfigForms } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
3
|
+
import { type RemoteSettings } from './RemoteSettingsCard.tsx';
|
|
3
4
|
import { type RemoteKey } from './locales.ts';
|
|
4
5
|
export type { RemoteEntryProps } from './RemoteEntry.tsx';
|
|
5
6
|
export type { PanelState, RemotePanelProps } from './RemotePanel.tsx';
|
|
6
7
|
export type { PairFailedNoticeProps } from './PairFailedNotice.tsx';
|
|
7
8
|
export type { RemoteKey } from './locales.ts';
|
|
8
9
|
export type { RemoteSettingsCardFace, RemoteSettingsCardState } from './RemoteSettingsCard.tsx';
|
|
9
|
-
export type { UpdateEntryProps } from './UpdateEntry.tsx';
|
|
10
|
-
export type { UpdatePanelProps, UpdateView } from './UpdatePanel.tsx';
|
|
11
10
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
12
11
|
interface LocaleNamespaceMap {
|
|
13
12
|
/** Mobile remote-control surface copy. */
|
|
@@ -62,6 +61,36 @@ declare module '@deepseek-ai/cordis' {
|
|
|
62
61
|
};
|
|
63
62
|
}
|
|
64
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* The profile entry id this package's own row carries, for a page that serves
|
|
66
|
+
* no family binder.
|
|
67
|
+
*
|
|
68
|
+
* The shared describe mirror answers asynchronously, so at plugin activation it
|
|
69
|
+
* usually holds nothing yet — and an unanswered or empty mirror is not evidence
|
|
70
|
+
* of absence. Binding the bare namespace there left the card bound to an entry
|
|
71
|
+
* the Host does not serve, and the form is bound once per session, so the card
|
|
72
|
+
* never recovered (every save answered `No configurable plugin entry`). The
|
|
73
|
+
* aggregate row id matches nearly every deployment; only a mirror that answers
|
|
74
|
+
* with OTHER plugins' rows falls back to the namespace itself (the pre-0.1.7
|
|
75
|
+
* keying shape), because that answer is the one that actually proves this
|
|
76
|
+
* package's own row is not served.
|
|
77
|
+
* @param forms - the shared configuration forms service.
|
|
78
|
+
* @returns the entry id to bind.
|
|
79
|
+
*/
|
|
80
|
+
export declare function servedEntryId(forms: ConfigForms): string;
|
|
81
|
+
/**
|
|
82
|
+
* Bind the settings form the remote-control card reads and writes.
|
|
83
|
+
*
|
|
84
|
+
* The family binder comes first: it resolves this package's family namespace
|
|
85
|
+
* onto the profile entry id the Host serves the form under, and keeps the
|
|
86
|
+
* loopback bridge as its own fallback. A page without that group (or one where
|
|
87
|
+
* its client half has not applied yet) binds through the shared forms service,
|
|
88
|
+
* on the entry id the describe mirror justifies and rebound as soon as the
|
|
89
|
+
* mirror answers — see {@link createServedEntryForm}.
|
|
90
|
+
* @param ctx - client context carrying the family binder and/or the shared forms service.
|
|
91
|
+
* @returns the form the card stages and saves through.
|
|
92
|
+
*/
|
|
93
|
+
export declare function bindSettingsForm(ctx: ClientContext): ConfigForm<RemoteSettings>;
|
|
65
94
|
/** Services required by this plugin. */
|
|
66
95
|
export declare const inject: string[];
|
|
67
96
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnE,OAAO,KAAK,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAA;AAczF,OAAO,EAAoD,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAChH,OAAO,EAAU,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAsBrD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACzD,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACrE,YAAY,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AACnE,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,YAAY,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAE/F,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,0CAA0C;QAC1C,MAAM,EAAE,SAAS,CAAA;KAClB;IAED,UAAU,OAAO;QACf;;;;WAIG;QACH;;;;;WAKG;QACH,oBAAoB,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,4BAA4B,CAAA;SAAE,CAAA;KAC3F;CACF;AAED,4GAA4G;AAC5G,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,IAAI,EAAE,OAAO,CAAA;CACd;AAED,mEAAmE;AACnE,MAAM,WAAW,4BAA4B;IAC3C,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,KAAK,CAAA;CACjB;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf;;;;;;;;;WASG;QACH,aAAa,CAAC,EAAE;YACd,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE;gBAAE,SAAS,EAAE,MAAM,CAAC;gBAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,CAAC,GAAG,SAAS,CAAA;aAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;SAClG,CAAA;KACF;CACF;AAmBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAUxD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,UAAU,CAAC,cAAc,CAAC,CAS/E;AAKD,wCAAwC;AACxC,eAAO,MAAM,MAAM,UAA6D,CAAA;AAEhF;;;GAGG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAwR9C"}
|
|
@@ -15,29 +15,76 @@ import { RemoteSettingsCard, RemoteSettingsCardController } from "./RemoteSettin
|
|
|
15
15
|
import { en, zh } from "./locales.js";
|
|
16
16
|
import { PAIR_FAILED_MARKER, runPairBootFlow } from "./deep-link.js";
|
|
17
17
|
import { readPairGatePolicy, sendHeartbeat, shouldStopHeartbeat } from "./pair-api.js";
|
|
18
|
-
import { channelTransition, installRemoteChannel,
|
|
18
|
+
import { channelTransition, installRemoteChannel, pageOriginFacts, remoteChannelRequired, REMOTE_CHANNEL_BOOT_GLOBAL, } from "./remote-channel.js";
|
|
19
|
+
import { isLocalPage } from "../remote-channel-rules.js";
|
|
19
20
|
import { FenceNotice } from "./FenceNotice.js";
|
|
20
21
|
import { reportDailyHeartbeat } from "./telemetry.js";
|
|
21
22
|
import { startMobileAdapt } from "./mobile-adapt.js";
|
|
22
23
|
import { installPluginCard } from "./plugin-card-seat.js";
|
|
24
|
+
import { createServedEntryForm } from "./settings-entry-form.js";
|
|
23
25
|
/** Dictionary namespace owned by this plugin. */
|
|
24
26
|
const NS = 'remote';
|
|
25
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Settings namespace the remote-control card edits: the family identity of
|
|
29
|
+
* this plugin's own settings form, and the row id a standalone bundle install
|
|
30
|
+
* carries.
|
|
31
|
+
*/
|
|
26
32
|
const REMOTE_WEB_UI_NS = 'remote-web-ui';
|
|
33
|
+
/** Profile entry id the family aggregate's generated row carries. */
|
|
27
34
|
const AGGREGATE_ENTRY_ID = 'web-ui-remote-web-ui';
|
|
35
|
+
/** Profile entry ids this package's patch rows carry, most specific first. */
|
|
28
36
|
const REMOTE_WEB_UI_ENTRY_IDS = [AGGREGATE_ENTRY_ID, 'ui-remote-web-ui', REMOTE_WEB_UI_NS];
|
|
29
|
-
|
|
37
|
+
/**
|
|
38
|
+
* The profile entry id this package's own row carries, for a page that serves
|
|
39
|
+
* no family binder.
|
|
40
|
+
*
|
|
41
|
+
* The shared describe mirror answers asynchronously, so at plugin activation it
|
|
42
|
+
* usually holds nothing yet — and an unanswered or empty mirror is not evidence
|
|
43
|
+
* of absence. Binding the bare namespace there left the card bound to an entry
|
|
44
|
+
* the Host does not serve, and the form is bound once per session, so the card
|
|
45
|
+
* never recovered (every save answered `No configurable plugin entry`). The
|
|
46
|
+
* aggregate row id matches nearly every deployment; only a mirror that answers
|
|
47
|
+
* with OTHER plugins' rows falls back to the namespace itself (the pre-0.1.7
|
|
48
|
+
* keying shape), because that answer is the one that actually proves this
|
|
49
|
+
* package's own row is not served.
|
|
50
|
+
* @param forms - the shared configuration forms service.
|
|
51
|
+
* @returns the entry id to bind.
|
|
52
|
+
*/
|
|
53
|
+
export function servedEntryId(forms) {
|
|
30
54
|
let served;
|
|
31
55
|
try {
|
|
32
56
|
served = forms.describe().getSnapshot().view?.namespaces.map(view => view.ns);
|
|
33
57
|
}
|
|
34
58
|
catch {
|
|
59
|
+
// A mirror that refuses the read is unanswered too, not absent.
|
|
35
60
|
served = undefined;
|
|
36
61
|
}
|
|
37
|
-
if (
|
|
38
|
-
return
|
|
62
|
+
if (served === undefined || served.length === 0)
|
|
63
|
+
return AGGREGATE_ENTRY_ID;
|
|
39
64
|
return REMOTE_WEB_UI_ENTRY_IDS.find(id => served.includes(id)) ?? REMOTE_WEB_UI_NS;
|
|
40
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Bind the settings form the remote-control card reads and writes.
|
|
68
|
+
*
|
|
69
|
+
* The family binder comes first: it resolves this package's family namespace
|
|
70
|
+
* onto the profile entry id the Host serves the form under, and keeps the
|
|
71
|
+
* loopback bridge as its own fallback. A page without that group (or one where
|
|
72
|
+
* its client half has not applied yet) binds through the shared forms service,
|
|
73
|
+
* on the entry id the describe mirror justifies and rebound as soon as the
|
|
74
|
+
* mirror answers — see {@link createServedEntryForm}.
|
|
75
|
+
* @param ctx - client context carrying the family binder and/or the shared forms service.
|
|
76
|
+
* @returns the form the card stages and saves through.
|
|
77
|
+
*/
|
|
78
|
+
export function bindSettingsForm(ctx) {
|
|
79
|
+
const family = ctx.get('webUiSettings');
|
|
80
|
+
if (family !== undefined && typeof family.bind === 'function') {
|
|
81
|
+
return family.bind({ namespace: REMOTE_WEB_UI_NS });
|
|
82
|
+
}
|
|
83
|
+
return createServedEntryForm({
|
|
84
|
+
forms: ctx.configForms,
|
|
85
|
+
entryIds: REMOTE_WEB_UI_ENTRY_IDS,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
41
88
|
/** Heartbeat cadence from a paired phone (presence + revocation liveness). */
|
|
42
89
|
const HEARTBEAT_INTERVAL_MS = 10_000;
|
|
43
90
|
/** Services required by this plugin. */
|
|
@@ -114,10 +161,7 @@ export function apply(ctx) {
|
|
|
114
161
|
// shared form (natively, or over its loopback bridge); without that group the
|
|
115
162
|
// namespace IS the owning entry id, so the official service is addressed
|
|
116
163
|
// directly.
|
|
117
|
-
const
|
|
118
|
-
const settingsForm = family !== undefined && typeof family.bind === 'function'
|
|
119
|
-
? family.bind({ namespace: REMOTE_WEB_UI_NS })
|
|
120
|
-
: ctx.configForms.get(servedEntryId(ctx.configForms));
|
|
164
|
+
const settingsForm = bindSettingsForm(ctx);
|
|
121
165
|
const enabled = () => {
|
|
122
166
|
const snapshot = settingsForm.getSnapshot();
|
|
123
167
|
return snapshot.status === 'ready'
|
|
@@ -246,7 +290,7 @@ export function apply(ctx) {
|
|
|
246
290
|
}
|
|
247
291
|
showFenceNotice();
|
|
248
292
|
};
|
|
249
|
-
const channelActive = () => remoteChannelRequired(window
|
|
293
|
+
const channelActive = () => remoteChannelRequired(pageOriginFacts(window), settingsForm.getSnapshot(), hostPairingPolicy);
|
|
250
294
|
// The parse-time boot patch (issue #987), when the served index carried
|
|
251
295
|
// it: already installed before any boot entry ran, so adopting its seat
|
|
252
296
|
// beats patching a second time (which would double-rewrite onto
|
|
@@ -299,7 +343,8 @@ export function apply(ctx) {
|
|
|
299
343
|
};
|
|
300
344
|
settingsForm.subscribe(syncChannel);
|
|
301
345
|
syncChannel();
|
|
302
|
-
|
|
346
|
+
const pageOrigin = pageOriginFacts(window);
|
|
347
|
+
if (!isLocalPage(pageOrigin.hostname, pageOrigin.protocol, pageOrigin.transportOwnsHost) && settingsForm.getSnapshot().status !== 'ready') {
|
|
303
348
|
void readPairGatePolicy().then((policy) => {
|
|
304
349
|
hostPairingPolicy = policy.requirePairingForLan;
|
|
305
350
|
syncChannel();
|
|
@@ -120,48 +120,6 @@ export declare const zh: {
|
|
|
120
120
|
'settings.unsaved': string;
|
|
121
121
|
'settings.saveFailed': string;
|
|
122
122
|
'settings.invalidNumber': string;
|
|
123
|
-
'update.label': string;
|
|
124
|
-
'update.badge': string;
|
|
125
|
-
'update.availableLabel': string;
|
|
126
|
-
'update.title': string;
|
|
127
|
-
'update.checking': string;
|
|
128
|
-
'update.upToDate': string;
|
|
129
|
-
'update.upToDateDetail': string;
|
|
130
|
-
'update.found': string;
|
|
131
|
-
'update.foundDetail': string;
|
|
132
|
-
'update.start': string;
|
|
133
|
-
'update.updating': string;
|
|
134
|
-
'update.cooldownNotice': string;
|
|
135
|
-
'update.updatingTitle': string;
|
|
136
|
-
'update.done': string;
|
|
137
|
-
'update.doneDetail': string;
|
|
138
|
-
'update.restartHint': string;
|
|
139
|
-
'update.linkMode': string;
|
|
140
|
-
'update.linkModeDetail': string;
|
|
141
|
-
'update.missing': string;
|
|
142
|
-
'update.missingDetail': string;
|
|
143
|
-
'update.offline': string;
|
|
144
|
-
'update.offlineDetail': string;
|
|
145
|
-
'update.unmounted': string;
|
|
146
|
-
'update.unmountedDetail': string;
|
|
147
|
-
'update.error': string;
|
|
148
|
-
'update.packages': string;
|
|
149
|
-
'update.releaseNotes': string;
|
|
150
|
-
'update.releaseFeatures': string;
|
|
151
|
-
'update.releaseFixes': string;
|
|
152
|
-
'update.releaseOther': string;
|
|
153
|
-
'update.releaseUnavailable': string;
|
|
154
|
-
'update.componentVersions': string;
|
|
155
|
-
'update.retry': string;
|
|
156
|
-
'update.close': string;
|
|
157
|
-
'update.error.pnpmMissing': string;
|
|
158
|
-
'update.error.timeout': string;
|
|
159
|
-
'update.error.notFound': string;
|
|
160
|
-
'update.error.link': string;
|
|
161
|
-
'update.error.pnpmFailed': string;
|
|
162
|
-
'update.error.stale': string;
|
|
163
|
-
'update.error.verifyFailed': string;
|
|
164
|
-
'update.error.unknown': string;
|
|
165
123
|
};
|
|
166
124
|
/** The remote namespace key union. */
|
|
167
125
|
export type RemoteKey = keyof typeof zh;
|
|
@@ -288,47 +246,5 @@ export declare const en: {
|
|
|
288
246
|
'settings.unsaved': string;
|
|
289
247
|
'settings.saveFailed': string;
|
|
290
248
|
'settings.invalidNumber': string;
|
|
291
|
-
'update.label': string;
|
|
292
|
-
'update.badge': string;
|
|
293
|
-
'update.availableLabel': string;
|
|
294
|
-
'update.title': string;
|
|
295
|
-
'update.checking': string;
|
|
296
|
-
'update.upToDate': string;
|
|
297
|
-
'update.upToDateDetail': string;
|
|
298
|
-
'update.found': string;
|
|
299
|
-
'update.foundDetail': string;
|
|
300
|
-
'update.start': string;
|
|
301
|
-
'update.updating': string;
|
|
302
|
-
'update.cooldownNotice': string;
|
|
303
|
-
'update.updatingTitle': string;
|
|
304
|
-
'update.done': string;
|
|
305
|
-
'update.doneDetail': string;
|
|
306
|
-
'update.restartHint': string;
|
|
307
|
-
'update.linkMode': string;
|
|
308
|
-
'update.linkModeDetail': string;
|
|
309
|
-
'update.missing': string;
|
|
310
|
-
'update.missingDetail': string;
|
|
311
|
-
'update.offline': string;
|
|
312
|
-
'update.offlineDetail': string;
|
|
313
|
-
'update.unmounted': string;
|
|
314
|
-
'update.unmountedDetail': string;
|
|
315
|
-
'update.error': string;
|
|
316
|
-
'update.packages': string;
|
|
317
|
-
'update.releaseNotes': string;
|
|
318
|
-
'update.releaseFeatures': string;
|
|
319
|
-
'update.releaseFixes': string;
|
|
320
|
-
'update.releaseOther': string;
|
|
321
|
-
'update.releaseUnavailable': string;
|
|
322
|
-
'update.componentVersions': string;
|
|
323
|
-
'update.retry': string;
|
|
324
|
-
'update.close': string;
|
|
325
|
-
'update.error.pnpmMissing': string;
|
|
326
|
-
'update.error.timeout': string;
|
|
327
|
-
'update.error.notFound': string;
|
|
328
|
-
'update.error.link': string;
|
|
329
|
-
'update.error.pnpmFailed': string;
|
|
330
|
-
'update.error.stale': string;
|
|
331
|
-
'update.error.verifyFailed': string;
|
|
332
|
-
'update.error.unknown': string;
|
|
333
249
|
};
|
|
334
250
|
//# sourceMappingURL=locales.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,mEAAmE;AACnE,eAAO,MAAM,EAAE
|
|
1
|
+
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,mEAAmE;AACnE,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0HmB,CAAA;AAElC,sCAAsC;AACtC,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,EAAE,CAAA;AAEvC,wDAAwD;AACxD,MAAM,MAAM,eAAe,GAAG,SAAS,CAAA;AAEvC,mEAAmE;AACnE,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0HsB,CAAA"}
|
|
@@ -14,7 +14,7 @@ export const zh = {
|
|
|
14
14
|
'status.disconnected': '已配对设备离线',
|
|
15
15
|
'status.stopped': '已停止远程访问',
|
|
16
16
|
'status.lanRequired': '此功能需要局域网绑定或公网地址才能使用',
|
|
17
|
-
'status.lanRequiredHint': '当前服务仅绑定在 127.0.0.1
|
|
17
|
+
'status.lanRequiredHint': '当前服务仅绑定在 127.0.0.1 且未配置公网地址,手机无法访问。请在本插件的设置卡片中打开“局域网访问”(装在全家桶里时在「设置 → Web 插件 → 远程访问设置」,单独安装时在设置 → 插件 → 本插件行),或用 dsh web --host 0.0.0.0 重新启动,或填写内网穿透的公网地址。',
|
|
18
18
|
'status.loopbackRequired': '配对面板仅限本机使用',
|
|
19
19
|
'status.loopbackRequiredHint': '请通过 http://127.0.0.1 打开此页面后重试;手机请使用配对链接访问。',
|
|
20
20
|
'status.unreachable': '无法连接配对服务',
|
|
@@ -122,48 +122,6 @@ export const zh = {
|
|
|
122
122
|
'settings.saveFailed': '部署未接受这些值,已保留供你修改。',
|
|
123
123
|
'settings.invalidNumber': '请输入数字,留空则使用默认值。',
|
|
124
124
|
// 更新面板(侧边栏更新按钮)。
|
|
125
|
-
'update.label': '检查更新',
|
|
126
|
-
'update.badge': '有更新',
|
|
127
|
-
'update.availableLabel': '发现新版本,检查更新',
|
|
128
|
-
'update.title': '检查更新',
|
|
129
|
-
'update.checking': '正在检查远程仓库中的新版本…',
|
|
130
|
-
'update.upToDate': '当前已是最新版本',
|
|
131
|
-
'update.upToDateDetail': '{name} 已是最新版本 v{version}。',
|
|
132
|
-
'update.found': '发现新版本',
|
|
133
|
-
'update.foundDetail': '{name} 有新版本 v{version}。确认后开始更新。',
|
|
134
|
-
'update.start': '开始更新',
|
|
135
|
-
'update.updating': '正在更新 {name} 至 v{version},可能需要 1-2 分钟…',
|
|
136
|
-
'update.cooldownNotice': '本次更新由你主动触发,将跳过 pnpm 的 24 小时发布冷却期(供应链保护)直接安装所选版本。',
|
|
137
|
-
'update.updatingTitle': '正在更新…',
|
|
138
|
-
'update.done': '更新完成',
|
|
139
|
-
'update.doneDetail': '所有组件已更新到最新版本。',
|
|
140
|
-
'update.restartHint': '请重启 dsh web 使新版本生效:在终端按 Ctrl+C 停止后重新运行 dsh web。',
|
|
141
|
-
'update.linkMode': '当前为本地开发模式',
|
|
142
|
-
'update.linkModeDetail': 'dsh-web 或其组件通过本地链接安装(开发模式),无法自动更新。npm 上最新版本:{version}。请同步本地仓库,或移除与全家桶重复的独立链接。',
|
|
143
|
-
'update.missing': '未找到 dsh-web 安装',
|
|
144
|
-
'update.missingDetail': '无法定位已安装的 dsh-web 聚合包。请先运行 dsh plugin --profile <profile> add @linxin666/dsh-web-all。',
|
|
145
|
-
'update.offline': '无法连接更新源',
|
|
146
|
-
'update.offlineDetail': '网络不可用或更新服务异常,请稍后重试。',
|
|
147
|
-
'update.unmounted': '更新服务未加载',
|
|
148
|
-
'update.unmountedDetail': '当前 dsh web 进程运行的插件版本不含更新服务,请重启 dsh web(Ctrl+C 后重新运行)后再试。',
|
|
149
|
-
'update.error': '更新失败',
|
|
150
|
-
'update.packages': '组件版本',
|
|
151
|
-
'update.releaseNotes': 'v{version} 更新说明',
|
|
152
|
-
'update.releaseFeatures': '新增功能',
|
|
153
|
-
'update.releaseFixes': '修复',
|
|
154
|
-
'update.releaseOther': '其他变动',
|
|
155
|
-
'update.releaseUnavailable': '本次发布说明暂不可用,可前往 GitHub Release 查看。',
|
|
156
|
-
'update.componentVersions': '查看组件版本',
|
|
157
|
-
'update.retry': '重新检查',
|
|
158
|
-
'update.close': '关闭更新面板',
|
|
159
|
-
'update.error.pnpmMissing': '未找到 pnpm,已尝试 pnpm / corepack / npx 仍不可用。请安装 pnpm 后重启应用(Windows: npm install -g pnpm 或 corepack enable;macOS: brew install pnpm 或 corepack enable)。',
|
|
160
|
-
'update.error.timeout': '更新超时,已终止安装进程,请重试。',
|
|
161
|
-
'update.error.notFound': '未找到 dsh-web 聚合包安装,无法更新。',
|
|
162
|
-
'update.error.link': 'dsh-web 或其组件使用本地链接,无法自动更新;请同步本地仓库,或移除与全家桶重复的独立链接。',
|
|
163
|
-
'update.error.pnpmFailed': '更新执行失败(pnpm 退出码 {code}),详见下方输出。',
|
|
164
|
-
'update.error.stale': '更新命令已执行,但安装版本未变化。常见原因:pnpm 11 的 minimumReleaseAge 门禁会静默跳过发布不足 24 小时的新版本。请在 profile 目录(~/.dsh/profiles/<profile>)的 pnpm-workspace.yaml 中配置 minimumReleaseAgeExclude(例如 "@linxin666/*")或 minimumReleaseAge: 0 后重新点击更新。',
|
|
165
|
-
'update.error.verifyFailed': '更新命令已执行,但无法核对安装后的版本(可能是 registry 探测失败或安装路径变化)。请查看下方输出,或稍后重试。',
|
|
166
|
-
'update.error.unknown': '更新失败,请重试。',
|
|
167
125
|
};
|
|
168
126
|
/** English dictionary, checked complete against the zh key set. */
|
|
169
127
|
export const en = {
|
|
@@ -180,7 +138,7 @@ export const en = {
|
|
|
180
138
|
'status.disconnected': 'Paired devices offline',
|
|
181
139
|
'status.stopped': 'Remote access stopped',
|
|
182
140
|
'status.lanRequired': 'This feature needs a LAN bind or a public address',
|
|
183
|
-
'status.lanRequiredHint': 'The server is bound to 127.0.0.1 and no public address is configured, so a phone cannot reach it. Turn on LAN access in
|
|
141
|
+
'status.lanRequiredHint': 'The server is bound to 127.0.0.1 and no public address is configured, so a phone cannot reach it. Turn on LAN access in this plugin settings card (under Settings → Web Plugins → Remote access when the full family is installed, or on this plugin row under Settings → Plugins for a standalone install), or restart with dsh web --host 0.0.0.0, or set the tunneled public address.',
|
|
184
142
|
'status.loopbackRequired': 'The pairing panel works on this machine only',
|
|
185
143
|
'status.loopbackRequiredHint': 'Open this page at http://127.0.0.1 to mint a QR code; phones use the paired link.',
|
|
186
144
|
'status.unreachable': 'Cannot reach the pairing service',
|
|
@@ -288,46 +246,4 @@ export const en = {
|
|
|
288
246
|
'settings.saveFailed': 'The deployment did not accept these values; they were left for you to correct.',
|
|
289
247
|
'settings.invalidNumber': 'Enter a number, or leave blank to use the default.',
|
|
290
248
|
// Update panel (the sidebar update trigger).
|
|
291
|
-
'update.label': 'Check for updates',
|
|
292
|
-
'update.badge': 'Update available',
|
|
293
|
-
'update.availableLabel': 'New version available. Check for updates',
|
|
294
|
-
'update.title': 'Check for updates',
|
|
295
|
-
'update.checking': 'Checking the remote repository for newer releases…',
|
|
296
|
-
'update.upToDate': 'Everything is up to date',
|
|
297
|
-
'update.upToDateDetail': '{name} is at the latest version v{version}.',
|
|
298
|
-
'update.found': 'A new version is available',
|
|
299
|
-
'update.foundDetail': '{name} has a newer release v{version}. Confirm to start the update.',
|
|
300
|
-
'update.start': 'Update now',
|
|
301
|
-
'update.updating': 'Updating {name} to v{version}; this may take 1-2 minutes…',
|
|
302
|
-
'update.cooldownNotice': 'This user-initiated update bypasses pnpm\'s 24-hour release cooldown (supply-chain protection) and installs the selected version immediately.',
|
|
303
|
-
'update.updatingTitle': 'Updating…',
|
|
304
|
-
'update.done': 'Update complete',
|
|
305
|
-
'update.doneDetail': 'All components are up to date.',
|
|
306
|
-
'update.restartHint': 'Restart dsh web for the new version to take effect: stop it with Ctrl+C in the terminal, then run dsh web again.',
|
|
307
|
-
'update.linkMode': 'Local development mode',
|
|
308
|
-
'update.linkModeDetail': 'dsh-web or one of its components is installed via a local link and cannot be updated remotely. Latest npm release: {version}. Sync the local checkout, or remove a standalone link duplicated by the aggregate.',
|
|
309
|
-
'update.missing': 'dsh-web not found',
|
|
310
|
-
'update.missingDetail': 'Could not locate the installed dsh-web aggregate package. Install it with: dsh plugin --profile <profile> add @linxin666/dsh-web-all',
|
|
311
|
-
'update.offline': 'Cannot reach the update source',
|
|
312
|
-
'update.offlineDetail': 'The network is unavailable or the update service is failing; try again later.',
|
|
313
|
-
'update.unmounted': 'The update service is not loaded',
|
|
314
|
-
'update.unmountedDetail': 'The running dsh web process loads a plugin build without the update service; restart dsh web (Ctrl+C, then run dsh web again) and retry.',
|
|
315
|
-
'update.error': 'Update failed',
|
|
316
|
-
'update.packages': 'Component versions',
|
|
317
|
-
'update.releaseNotes': 'v{version} release notes',
|
|
318
|
-
'update.releaseFeatures': 'New Features',
|
|
319
|
-
'update.releaseFixes': 'Bug Fixes',
|
|
320
|
-
'update.releaseOther': 'Other Changes',
|
|
321
|
-
'update.releaseUnavailable': 'Release notes are unavailable for this version; see the GitHub release instead.',
|
|
322
|
-
'update.componentVersions': 'View component versions',
|
|
323
|
-
'update.retry': 'Check again',
|
|
324
|
-
'update.close': 'Close update panel',
|
|
325
|
-
'update.error.pnpmMissing': 'pnpm was not found (tried pnpm / corepack / npx). Install pnpm and restart the app (Windows: npm install -g pnpm or corepack enable; macOS: brew install pnpm or corepack enable).',
|
|
326
|
-
'update.error.timeout': 'The update timed out and the install process was killed; try again.',
|
|
327
|
-
'update.error.notFound': 'The dsh-web aggregate package is not installed; nothing to update.',
|
|
328
|
-
'update.error.link': 'dsh-web or one of its components uses a local link. Sync the checkout, or remove a standalone link duplicated by the aggregate.',
|
|
329
|
-
'update.error.pnpmFailed': 'The update failed (pnpm exited with code {code}); see the output below.',
|
|
330
|
-
'update.error.stale': 'The update command ran but the installed versions did not change. Likely cause: the pnpm 11 minimumReleaseAge gate silently skips releases published less than 24 hours ago. Add minimumReleaseAgeExclude (e.g. "@linxin666/*") or set minimumReleaseAge: 0 in pnpm-workspace.yaml under the profile directory (~/.dsh/profiles/<profile>), then run the update again.',
|
|
331
|
-
'update.error.verifyFailed': 'The update command ran but the installed versions could not be verified afterwards (registry probe failed or the install path changed). Inspect the output below, or retry later.',
|
|
332
|
-
'update.error.unknown': 'Update failed; try again.',
|
|
333
249
|
};
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Browser-side wire helpers for the /api/pair surface. Plain fetch over
|
|
3
3
|
* same-origin /api (like the connection client); JSON bodies, string
|
|
4
4
|
* responses for the error codes.
|
|
5
|
+
*
|
|
6
|
+
* The paths are DOCUMENT-RELATIVE (issue #1707): the GUI is served with
|
|
7
|
+
* `<base href="./">`, so a sub-path deployment resolves them against its entry
|
|
8
|
+
* directory instead of escaping to the origin root.
|
|
5
9
|
*/
|
|
6
10
|
/** issue() response. */
|
|
7
11
|
export interface IssueResult {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pair-api.d.ts","sourceRoot":"","sources":["../../../src/client/pair-api.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pair-api.d.ts","sourceRoot":"","sources":["../../../src/client/pair-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
* Browser-side wire helpers for the /api/pair surface. Plain fetch over
|
|
3
3
|
* same-origin /api (like the connection client); JSON bodies, string
|
|
4
4
|
* responses for the error codes.
|
|
5
|
+
*
|
|
6
|
+
* The paths are DOCUMENT-RELATIVE (issue #1707): the GUI is served with
|
|
7
|
+
* `<base href="./">`, so a sub-path deployment resolves them against its entry
|
|
8
|
+
* directory instead of escaping to the origin root.
|
|
5
9
|
*/
|
|
6
10
|
/** Read the host-authoritative desktop pairing policy. */
|
|
7
11
|
export async function readPairGatePolicy() {
|
|
8
|
-
const response = await fetch('
|
|
12
|
+
const response = await fetch('api/pair/status');
|
|
9
13
|
if (!response.ok)
|
|
10
14
|
throw new Error(`remote-web-ui: status failed with ${String(response.status)}`);
|
|
11
15
|
const value = await response.json();
|
|
@@ -25,7 +29,7 @@ export async function readPairGatePolicy() {
|
|
|
25
29
|
* origin — the panel is a desktop control endpoint).
|
|
26
30
|
*/
|
|
27
31
|
export async function issuePair(address) {
|
|
28
|
-
const response = await fetch('
|
|
32
|
+
const response = await fetch('api/pair/issue', {
|
|
29
33
|
method: 'POST',
|
|
30
34
|
headers: { 'content-type': 'application/json' },
|
|
31
35
|
body: JSON.stringify({
|
|
@@ -50,7 +54,7 @@ export async function issuePair(address) {
|
|
|
50
54
|
* @returns the wire result.
|
|
51
55
|
*/
|
|
52
56
|
export async function acceptPair(token) {
|
|
53
|
-
const response = await fetch('
|
|
57
|
+
const response = await fetch('api/pair/accept', {
|
|
54
58
|
method: 'POST',
|
|
55
59
|
headers: { 'content-type': 'application/json' },
|
|
56
60
|
body: JSON.stringify({ token }),
|
|
@@ -65,7 +69,7 @@ export async function acceptPair(token) {
|
|
|
65
69
|
}
|
|
66
70
|
/** Revoke mobile access (paired devices + the current token). */
|
|
67
71
|
export async function stopPair() {
|
|
68
|
-
const response = await fetch('
|
|
72
|
+
const response = await fetch('api/pair/stop', { method: 'POST' });
|
|
69
73
|
if (!response.ok)
|
|
70
74
|
throw new Error(`remote-web-ui: stop failed with ${String(response.status)}`);
|
|
71
75
|
}
|
|
@@ -74,7 +78,7 @@ export async function stopPair() {
|
|
|
74
78
|
* @param deviceId - the session id of the row to drop.
|
|
75
79
|
*/
|
|
76
80
|
export async function revokePair(deviceId) {
|
|
77
|
-
const response = await fetch('
|
|
81
|
+
const response = await fetch('api/pair/revoke', {
|
|
78
82
|
method: 'POST',
|
|
79
83
|
headers: { 'content-type': 'application/json' },
|
|
80
84
|
body: JSON.stringify({ deviceId }),
|
|
@@ -90,7 +94,7 @@ export async function revokePair(deviceId) {
|
|
|
90
94
|
* proves this page is not paired (see {@link shouldStopHeartbeat}).
|
|
91
95
|
*/
|
|
92
96
|
export async function sendHeartbeat() {
|
|
93
|
-
const response = await fetch('
|
|
97
|
+
const response = await fetch('api/pair/heartbeat', { method: 'POST' });
|
|
94
98
|
return response.status;
|
|
95
99
|
}
|
|
96
100
|
/**
|
|
@@ -135,7 +139,7 @@ export class LanBindStatusError extends Error {
|
|
|
135
139
|
}
|
|
136
140
|
/** Read the LAN-bind facts (loopback-only endpoint). */
|
|
137
141
|
export async function readLanBindStatus() {
|
|
138
|
-
const response = await fetch('
|
|
142
|
+
const response = await fetch('api/pair/lan-bind');
|
|
139
143
|
if (!response.ok)
|
|
140
144
|
throw new LanBindStatusError(response.status, `remote-web-ui: lan-bind status failed with ${String(response.status)}`);
|
|
141
145
|
return await response.json();
|