@wenbin_wb/dsh-bridge 2.0.0 → 2.0.2

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.md CHANGED
@@ -87,6 +87,16 @@ dsh plugin --profile web add ./dsh-bridge
87
87
 
88
88
  After installation, restart DSH and find "Remote Access" in settings.
89
89
 
90
+ ### Upgrade to latest
91
+
92
+ ```bash
93
+ dsh plugin --profile web add @wenbin_wb/dsh-bridge@latest
94
+ ```
95
+
96
+ > **Note**: `update --latest` may fail to reach the newest major version due to version constraints from already-installed dependencies. Use the `add @latest` command above to force-install the latest version (no need to know the exact version number).
97
+
98
+ After upgrading, restart DSH and **hard-refresh** the browser (Windows: `Ctrl+Shift+R`, macOS: `Cmd+Shift+R`) to clear the cache, then confirm the latest version is shown in settings.
99
+
90
100
  ---
91
101
 
92
102
  ## Usage
package/README.zh-CN.md CHANGED
@@ -87,6 +87,16 @@ dsh plugin --profile web add ./dsh-bridge
87
87
 
88
88
  安装完成后重启 DSH,在设置页找到「远程访问」即可使用。
89
89
 
90
+ ### 升级到最新版
91
+
92
+ ```bash
93
+ dsh plugin --profile web add @wenbin_wb/dsh-bridge@latest
94
+ ```
95
+
96
+ > **注意**:`update --latest` 可能因已安装依赖的版本约束而无法升级到最新版。用上面的 `add @latest` 命令即可强制安装最新版(无需知道具体版本号)。
97
+
98
+ 升级完成后重启 DSH,并在浏览器**硬刷新**(Windows: `Ctrl+Shift+R`,macOS: `Cmd+Shift+R`)清除缓存,然后确认设置页显示最新版本号。
99
+
90
100
  ---
91
101
 
92
102
  ## 使用
package/client/client.js CHANGED
@@ -62,8 +62,10 @@ var BRIDGE_ENDPOINTS = {
62
62
 
63
63
  // client/index.js
64
64
  var GITHUB_URL = "https://github.com/wenbin-wb/dsh-bridge";
65
+ var RELEASES_URL = "https://github.com/wenbin-wb/dsh-bridge/releases";
65
66
  var ISSUES_URL = "https://github.com/wenbin-wb/dsh-bridge/issues/new";
66
67
  var TUNNEL_DOCS_URL = "https://github.com/wenbin-wb/dsh-bridge/blob/main/docs/custom-tunnel.md";
68
+ var UPGRADE_COMMAND = "dsh plugin --profile web add @wenbin_wb/dsh-bridge@latest";
67
69
  var name = "dsh-bridge";
68
70
  var inject = ["slots", "connection"];
69
71
  function semverGt(a, b) {
@@ -95,6 +97,32 @@ var s = {
95
97
  warn: { background: "var(--dsw-alias-state-warn-bg,#fffbeb)", border: "1px solid var(--dsw-alias-state-warn-border,#fde68a)", borderRadius: 8, padding: "10px 14px", fontSize: 12, color: "var(--dsw-alias-state-warn-primary,#92400e)", lineHeight: 1.6 },
96
98
  tip: { background: "var(--dsw-alias-bg-layer-2,#f9fafb)", borderRadius: 8, padding: "10px 14px", fontSize: 12, color: "var(--dsw-alias-label-secondary,#6b7280)", lineHeight: 1.6 }
97
99
  };
100
+ function useCopy() {
101
+ const [copied, setCopied] = React.useState(false);
102
+ const copy = React.useCallback((text) => {
103
+ const done = () => {
104
+ setCopied(true);
105
+ setTimeout(() => setCopied(false), 2e3);
106
+ };
107
+ if (navigator.clipboard?.writeText) {
108
+ navigator.clipboard.writeText(text).then(done).catch(() => fallbackCopy());
109
+ } else {
110
+ fallbackCopy();
111
+ }
112
+ function fallbackCopy() {
113
+ const textarea = document.createElement("textarea");
114
+ textarea.value = text;
115
+ textarea.style.position = "fixed";
116
+ textarea.style.opacity = "0";
117
+ document.body.appendChild(textarea);
118
+ textarea.select();
119
+ const success = document.execCommand("copy");
120
+ document.body.removeChild(textarea);
121
+ if (success) done();
122
+ }
123
+ }, []);
124
+ return [copied, copy];
125
+ }
98
126
  function StatusTag({ running }) {
99
127
  return React.createElement("span", {
100
128
  style: {
@@ -589,6 +617,7 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
589
617
  function VersionBanner({ rpcCall }) {
590
618
  const [info, setInfo] = React.useState(null);
591
619
  const [loading, setLoading] = React.useState(false);
620
+ const [copied, copy] = useCopy();
592
621
  const check = React.useCallback(async () => {
593
622
  setLoading(true);
594
623
  try {
@@ -604,13 +633,19 @@ function VersionBanner({ rpcCall }) {
604
633
  const hasUpdate = info?.latest && info?.current && !info.error && semverGt(info.latest, info.current);
605
634
  const links = React.createElement(
606
635
  "div",
607
- { style: { display: "flex", gap: 12, alignItems: "center" } },
636
+ { style: { display: "flex", gap: 12, alignItems: "center", flexWrap: "wrap" } },
608
637
  React.createElement("a", {
609
638
  href: GITHUB_URL,
610
639
  target: "_blank",
611
640
  rel: "noreferrer",
612
641
  style: s.btnLink
613
642
  }, "\u2B50 GitHub"),
643
+ React.createElement("a", {
644
+ href: RELEASES_URL,
645
+ target: "_blank",
646
+ rel: "noreferrer",
647
+ style: s.btnLink
648
+ }, "\u{1F4CB} \u66F4\u65B0\u65E5\u5FD7"),
614
649
  React.createElement("a", {
615
650
  href: ISSUES_URL,
616
651
  target: "_blank",
@@ -639,23 +674,36 @@ function VersionBanner({ rpcCall }) {
639
674
  React.createElement("span", { style: { fontSize: 20 } }, "\u{1F389}"),
640
675
  React.createElement(
641
676
  "div",
642
- { style: { flex: 1 } },
677
+ { style: { flex: 1, minWidth: 0 } },
643
678
  React.createElement("div", {
644
679
  style: {
645
680
  fontSize: 13,
646
681
  fontWeight: 600,
647
682
  color: "var(--dsw-alias-state-info-primary,#1e40af)",
648
- marginBottom: 4
683
+ marginBottom: 6
649
684
  }
650
685
  }, `\u53D1\u73B0\u65B0\u7248\u672C v${info.latest}\uFF08\u5F53\u524D v${info.current}\uFF09`),
651
- React.createElement("code", {
652
- style: {
653
- ...s.code,
654
- fontSize: 11,
655
- color: "var(--dsw-alias-label-secondary,#6b7280)",
656
- display: "block"
657
- }
658
- }, "dsh plugin --profile web update @wenbin_wb/dsh-bridge --latest")
686
+ React.createElement(
687
+ "div",
688
+ {
689
+ style: { display: "flex", alignItems: "center", gap: 8 }
690
+ },
691
+ React.createElement("code", {
692
+ style: {
693
+ ...s.code,
694
+ fontSize: 11,
695
+ color: "var(--dsw-alias-label-secondary,#6b7280)",
696
+ flex: 1,
697
+ minWidth: 0,
698
+ wordBreak: "break-all"
699
+ }
700
+ }, UPGRADE_COMMAND),
701
+ React.createElement("button", {
702
+ style: { ...s.btnGhost, height: 26, padding: "0 10px", fontSize: 12, flexShrink: 0 },
703
+ onClick: () => copy(UPGRADE_COMMAND),
704
+ title: "\u590D\u5236\u5347\u7EA7\u547D\u4EE4"
705
+ }, copied ? "\u2713 \u5DF2\u590D\u5236" : "\u590D\u5236")
706
+ )
659
707
  ),
660
708
  React.createElement("button", {
661
709
  style: {
package/client/index.js CHANGED
@@ -3,9 +3,13 @@
3
3
  import { BRIDGE_RPC_CHANNEL, BRIDGE_ENDPOINTS } from '../lib/bridge-rpc-constants.js';
4
4
 
5
5
  const GITHUB_URL = 'https://github.com/wenbin-wb/dsh-bridge';
6
+ const RELEASES_URL = 'https://github.com/wenbin-wb/dsh-bridge/releases';
6
7
  const ISSUES_URL = 'https://github.com/wenbin-wb/dsh-bridge/issues/new';
7
8
  const TUNNEL_DOCS_URL = 'https://github.com/wenbin-wb/dsh-bridge/blob/main/docs/custom-tunnel.md';
8
9
 
10
+ // 升级命令:用 add @latest 强制安装最新版(update --latest 受已安装依赖版本约束可能无法升级到最新版)
11
+ const UPGRADE_COMMAND = 'dsh plugin --profile web add @wenbin_wb/dsh-bridge@latest';
12
+
9
13
  const name = 'dsh-bridge';
10
14
  const inject = ['slots', 'connection'];
11
15
 
@@ -43,6 +47,35 @@ const s = {
43
47
 
44
48
  // ---- 子组件 ----
45
49
 
50
+ // 通用复制 hook:返回 [copied, copy],copy(text) 复制文本并短暂显示成功状态
51
+ function useCopy() {
52
+ const [copied, setCopied] = React.useState(false);
53
+ const copy = React.useCallback((text) => {
54
+ const done = () => {
55
+ setCopied(true);
56
+ setTimeout(() => setCopied(false), 2000);
57
+ };
58
+ if (navigator.clipboard?.writeText) {
59
+ navigator.clipboard.writeText(text).then(done).catch(() => fallbackCopy());
60
+ } else {
61
+ fallbackCopy();
62
+ }
63
+ // 降级方案:使用 document.execCommand (HTTP 环境下 Clipboard API 不可用)
64
+ function fallbackCopy() {
65
+ const textarea = document.createElement('textarea');
66
+ textarea.value = text;
67
+ textarea.style.position = 'fixed';
68
+ textarea.style.opacity = '0';
69
+ document.body.appendChild(textarea);
70
+ textarea.select();
71
+ const success = document.execCommand('copy');
72
+ document.body.removeChild(textarea);
73
+ if (success) done();
74
+ }
75
+ }, []);
76
+ return [copied, copy];
77
+ }
78
+
46
79
  function StatusTag({ running }) {
47
80
  return React.createElement('span', {
48
81
  style: {
@@ -507,8 +540,10 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
507
540
  }
508
541
 
509
542
  // 版本检查 + GitHub/反馈入口
510
- function VersionBanner({ rpcCall }) { const [info, setInfo] = React.useState(null);
543
+ function VersionBanner({ rpcCall }) {
544
+ const [info, setInfo] = React.useState(null);
511
545
  const [loading, setLoading] = React.useState(false);
546
+ const [copied, copy] = useCopy();
512
547
 
513
548
  const check = React.useCallback(async () => {
514
549
  setLoading(true);
@@ -525,11 +560,14 @@ function VersionBanner({ rpcCall }) { const [info, setInfo] = React.useState(nu
525
560
  // 只有 npm 上的版本严格大于当前版本才算有新版本
526
561
  const hasUpdate = info?.latest && info?.current && !info.error && semverGt(info.latest, info.current);
527
562
 
528
- // 链接按钮组:GitHub + 反馈 Bug
529
- const links = React.createElement('div', { style: { display: 'flex', gap: 12, alignItems: 'center' } },
563
+ // 链接按钮组:GitHub + 更新日志 + 反馈 Bug
564
+ const links = React.createElement('div', { style: { display: 'flex', gap: 12, alignItems: 'center', flexWrap: 'wrap' } },
530
565
  React.createElement('a', {
531
566
  href: GITHUB_URL, target: '_blank', rel: 'noreferrer', style: s.btnLink,
532
567
  }, '⭐ GitHub'),
568
+ React.createElement('a', {
569
+ href: RELEASES_URL, target: '_blank', rel: 'noreferrer', style: s.btnLink,
570
+ }, '📋 更新日志'),
533
571
  React.createElement('a', {
534
572
  href: ISSUES_URL, target: '_blank', rel: 'noreferrer', style: s.btnLink,
535
573
  }, '🐛 反馈 Bug'),
@@ -549,23 +587,34 @@ function VersionBanner({ rpcCall }) { const [info, setInfo] = React.useState(nu
549
587
  },
550
588
  React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 12 } },
551
589
  React.createElement('span', { style: { fontSize: 20 } }, '🎉'),
552
- React.createElement('div', { style: { flex: 1 } },
590
+ React.createElement('div', { style: { flex: 1, minWidth: 0 } },
553
591
  React.createElement('div', {
554
592
  style: {
555
593
  fontSize: 13,
556
594
  fontWeight: 600,
557
595
  color: 'var(--dsw-alias-state-info-primary,#1e40af)',
558
- marginBottom: 4,
596
+ marginBottom: 6,
559
597
  },
560
598
  }, `发现新版本 v${info.latest}(当前 v${info.current})`),
561
- React.createElement('code', {
562
- style: {
563
- ...s.code,
564
- fontSize: 11,
565
- color: 'var(--dsw-alias-label-secondary,#6b7280)',
566
- display: 'block',
567
- },
568
- }, 'dsh plugin --profile web update @wenbin_wb/dsh-bridge --latest'),
599
+ React.createElement('div', {
600
+ style: { display: 'flex', alignItems: 'center', gap: 8 },
601
+ },
602
+ React.createElement('code', {
603
+ style: {
604
+ ...s.code,
605
+ fontSize: 11,
606
+ color: 'var(--dsw-alias-label-secondary,#6b7280)',
607
+ flex: 1,
608
+ minWidth: 0,
609
+ wordBreak: 'break-all',
610
+ },
611
+ }, UPGRADE_COMMAND),
612
+ React.createElement('button', {
613
+ style: { ...s.btnGhost, height: 26, padding: '0 10px', fontSize: 12, flexShrink: 0 },
614
+ onClick: () => copy(UPGRADE_COMMAND),
615
+ title: '复制升级命令',
616
+ }, copied ? '✓ 已复制' : '复制'),
617
+ ),
569
618
  ),
570
619
  React.createElement('button', {
571
620
  style: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wenbin_wb/dsh-bridge",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "手机扫码即可在移动端/公网继续用 DeepSeek Harness,人不在电脑前也能接着干。一键局域网二维码、Cloudflare 公网隧道、自建隧道与微信 Bot(多工作区/会话持久化/媒体/审批),无需自己搭公网服务器。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",