source-code-mgmt 1.10.0 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +11 -2
- package/README.md +16 -5
- package/lib/client.js +104 -16
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# source-code-mgmt — DSH Source Code Management Plugin
|
|
2
2
|
|
|
3
|
-
> Version: **v1.10.
|
|
3
|
+
> Version: **v1.10.1** | 中文版见 [README.md](README.md)
|
|
4
4
|
|
|
5
5
|
> A source-code management plugin for the DSH Web GUI: it bundles「environment check → SSH setup → commit/push/upload code」into one「Code Management」panel with GitHub / Gitee dual-platform support.
|
|
6
6
|
|
|
@@ -196,7 +196,16 @@ dsh plugin --profile web add link:$(pwd)
|
|
|
196
196
|
|
|
197
197
|
## Version history
|
|
198
198
|
|
|
199
|
-
### v1.10.
|
|
199
|
+
### v1.10.1 (current)
|
|
200
|
+
- **Fix: the top-right「代码管理」button lingered even after dsh-better-sidebar was installed.** For the fallback entry (better-sidebar absent) the teardown handler was only wired for the ReactDOM fallback path — the slots path never stored it, so switching to the sidebar-Tab form left the header entry behind. The `slots.inject` disposer is now captured into `entryUnmount`, so switching to a Tab tears the header entry down correctly.
|
|
201
|
+
- **Fix: when better-sidebar is absent, the entry only showed inside a conversation and vanished in the new-conversation / no-conversation empty state.** The old entry lived in `conversation.session.header.utilities` (`scope: 'session'`), and the whole session header is hidden via `hideChrome` in the empty state. It is now **always present at the top-right**: with an active session it sits beside「Session log」(the right-aligned session-header utilities); in the new/no-conversation empty state it becomes a fixed top-right button registered in the always-mounted `shell.overlay` slot (shown only when the session is blank or absent, so it never duplicates the header button).
|
|
202
|
+
- **Fix: on refresh the「代码管理」button overlapped「Session log」.** `captureSessions()` takes ~1.2s to populate the session list, and before that the button wrongly believed there was no session and lit up early. The overlap button now renders nothing until the session list is captured.
|
|
203
|
+
- **Corrected visibility signal:** the fixed button now keys off whether the current session is blank (`sessions.list.getSnapshot().byId[current].blank`) — show only for blank/no-session, hide for an active (non-blank) session — replacing the inaccurate `current === undefined` check.
|
|
204
|
+
- **Robustness:** better-sidebar detection now uses a **bounded multi-tick retry** (fast start then slowing, ~44s, stopping on success and cleared on teardown) instead of a single 1.5s retry, covering slow client cold-start so the Tab-switch race no longer misses.
|
|
205
|
+
|
|
206
|
+
> All changes are client-side (`lib/client.js`); refresh the page to pick them up. Host `/api` routes and the push/ignore logic are untouched.
|
|
207
|
+
|
|
208
|
+
### v1.10.0 (history)
|
|
200
209
|
- **Bilingual UI, live (follows DSH's language setting)**: every piece of panel copy (steps ①②③, buttons, dialogs, status/result messages, confirm dialogs, the sidebar Tab title) plus host-side error/result messages is now driven by a bilingual dictionary. Language comes from DSH's Settings → General → Language and switches **instantly** — the panel re-renders via a `ctx.locale` subscription (the Tab title follows too), no refresh or restart. The host returns messages per-request based on `?lang=` (AsyncLocalStorage-scoped, so concurrent requests never cross languages). The Chinese UI is byte-identical to v1.9.0; English is a complete translation (including >100MB skip reasons, Gitee token hints, git command fallback messages). The `tools/` directory now holds the i18n extract/apply/test scripts for future maintenance.
|
|
201
210
|
|
|
202
211
|
### v1.9.0 (history)
|
package/README.md
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
> [English](README.en.md) | 中文
|
|
4
4
|
|
|
5
|
-
> 版本:**v1.10.
|
|
5
|
+
> 版本:**v1.10.1** | 更新日志见文末「[版本历史](#版本历史)」
|
|
6
6
|
|
|
7
7
|
> **界面语言跟随 DSH 设置实时切换**:面板与 host 端消息自动使用 DSH 的语言(设置 → 通用 → 语言),中文 ↔ 英文即时生效,无需重启。
|
|
8
8
|
|
|
9
9
|
> DSH Web GUI 源代码管理插件:把「环境检查 → SSH 配置 → 代码上传推送」整合进「代码管理」面板,支持 GitHub / Gitee 双平台,一键管理代码仓库。
|
|
10
10
|
|
|
11
|
-
> 入口位置自适应:**已安装 [dsh-better-sidebar](https://github.com/omdsh-dev/DSH-better-sidebar) 时**,「代码管理」作为它侧边栏的一个新 Tab 页面出现(全新侧边栏 Tab
|
|
11
|
+
> 入口位置自适应:**已安装 [dsh-better-sidebar](https://github.com/omdsh-dev/DSH-better-sidebar) 时**,「代码管理」作为它侧边栏的一个新 Tab 页面出现(全新侧边栏 Tab);**未安装时**,「代码管理」按钮位于 DSH **右上角、常驻可见**——有会话时放在「Session 日志」旁边的右对齐列表里,无会话空态时改为一个固定在**右上角**的浮动按钮,点击后打开一个 **dsh-better-sidebar 外观的右侧集成面板**(推挤主内容区)。两种形态都复用同一套面板 UI。
|
|
12
12
|
|
|
13
13
|
## 功能
|
|
14
14
|
|
|
15
15
|
集成入口(二选一,自动检测,无需手动切换):
|
|
16
16
|
|
|
17
17
|
- **已安装 dsh-better-sidebar**:「代码管理」注册为它侧边栏的一个**新 Tab 页面**,点击侧边栏 Tab 直接打开面板;
|
|
18
|
-
- **未安装 dsh-better-sidebar
|
|
18
|
+
- **未安装 dsh-better-sidebar**:「代码管理」按钮常驻在 DSH **右上角**——有活跃(非空白)会话时通过 `conversation.session.header.utilities` 槽位放在「Session 日志」旁(同款胶囊、间距一致);空白(新对话)/无会话空态时通过常驻的 `shell.overlay` 槽注册一个固定在右上角的浮动按钮(仅空白或没有会话时显示,活跃会话时交给 header 内的按钮,避免重复)。点击都打开一个 **dsh-better-sidebar 外观的右侧集成面板**(内容放同一面板),并把主内容区往左推挤。
|
|
19
19
|
|
|
20
|
-
> 检测只是激活时一次内存读取(`ctx.get('betterSidebar')`),零 I/O、零网络,不影响 DSH
|
|
20
|
+
> 检测只是激活时一次内存读取(`ctx.get('betterSidebar')`),零 I/O、零网络,不影响 DSH 启动速度;两种形态间自动切换。未安装 better-sidebar 时入口常驻右上角(有会话=Session 日志旁,空态=固定右上角浮动按钮),空态/新对话也可见。
|
|
21
21
|
|
|
22
22
|
面板分三步:
|
|
23
23
|
|
|
@@ -197,7 +197,18 @@ dsh plugin --profile web add link:$(pwd)
|
|
|
197
197
|
|
|
198
198
|
## 版本历史
|
|
199
199
|
|
|
200
|
-
### v1.10.
|
|
200
|
+
### v1.10.1(当前)
|
|
201
|
+
本次更新(修复 better-sidebar 集成与「未安装 better-sidebar」时入口的若干问题):
|
|
202
|
+
|
|
203
|
+
- **修复:装了 dsh-better-sidebar 后,右上角「代码管理」按钮仍残留**。根因:未装 better-sidebar 时的降级入口此前只给 ReactDOM 降级路径赋了 `entryUnmount`,slots 路径漏了——导致切到「侧边栏 Tab」形态时 header 入口没被拆掉。现已把 `slots.inject` 返回的 disposer 记进 `entryUnmount`,切到 Tab 时正确拆除(顺带修正同类清理逻辑)。
|
|
204
|
+
- **修复:未安装 better-sidebar 时,入口只在对话内显示,新对话/无会话空态不显示**。根因:旧入口挂 `conversation.session.header.utilities`(`scope: 'session'`),而空态时整个会话 header 被 `hideChrome` 隐藏,按钮出不来。现在改为**右上角常驻**——有活跃会话时放在「Session 日志」旁(会话 header 的右对齐列表),新对话/无会话空态时改为 `shell.overlay` 常驻槽里 `position: fixed` 钉在右上角的按钮(仅空白/无会话时显示,避免与 header 按钮重复)。
|
|
205
|
+
- **修复:刷新瞬间「代码管理」按钮与「Session 日志」重叠**。根因:`captureSessions()` 延迟 1.2s 才捕获到 session 列表,捕获前误判为「无会话」而提前点亮常驻按钮。现在未捕获到 session 列表前不渲染常驻按钮,杜绝刷新闪叠。
|
|
206
|
+
- **判定信号修正**:常驻按钮的显隐改用「当前会话是否空白」判断(`sessions.list.getSnapshot().byId[current].blank`)——活跃(非空白)会话才隐藏常驻按钮(交给 header 内的按钮),空白/无会话则显示,替代原来不准确的「`current === undefined`」判断。
|
|
207
|
+
- **健壮性**:better-sidebar 服务的探测由「一次性 1.5s 重试」改为**有界多档重试**(快节奏起步再放慢,覆盖约 44s,拿到即停、卸载即清),兜底 better-sidebar 客户端冷启动较慢导致漏切 Tab 的竞态。
|
|
208
|
+
|
|
209
|
+
> 以上均为客户端(`lib/client.js`)改动,刷新页面即生效;host 端 `/api` 路由与推送/忽略逻辑未改动。
|
|
210
|
+
|
|
211
|
+
### v1.10.0(历史)
|
|
201
212
|
本次更新:
|
|
202
213
|
|
|
203
214
|
- **界面中英文实时切换(跟随 DSH 语言设置)**:面板全部文案(①②③ 三步、按钮、弹窗、状态/结果消息、确认框、Tab 标题)与 host 端错误/结果消息改为双语词典驱动——语言 = DSH 设置 → 通用 → 语言,切换**即时生效**(面板经 `ctx.locale` 订阅实时重渲染,Tab 标题随动),无需刷新/重启;host 端按请求的 `?lang=` 经 AsyncLocalStorage 按请求返回对应语言,并发不串扰。中文界面与 v1.9.0 完全一致,英文界面为完整翻译(含 >100MB 忽略原因、Gitee 令牌提示、git 命令失败回退等全部消息)。新增 `tools/` 下的 i18n 提取/应用/测试脚本便于后续维护
|
package/lib/client.js
CHANGED
|
@@ -179,9 +179,10 @@ window.__ModuleLoader__.load({
|
|
|
179
179
|
const h = React.createElement;
|
|
180
180
|
|
|
181
181
|
// ---------- i18n: follows DSH’s language setting (Settings → General → Language), live ----------
|
|
182
|
-
const EN_DICT = {"展开":"Expand","折叠":"Collapse","展开该部分":"Expand this section","折叠该部分":"Collapse this section","已安装":"Installed","❌ 未安装":"❌ Not installed","复制安装命令":"Copy install command","一键安装(会自动选包管理器)":"Install automatically (picks a package manager)","安装中…":"Installing…","安装":"Install"," 执行成功":" executed successfully","(如未生效需以管理员身份重试)":" (retry as administrator if it did not take effect)","安装失败":"Install failed","① 环境检查":"① Environment","✅ 均存在":"✅ All present","操作系统":"OS","已找到":"Found","检测中":"Checking","失败: ":"Failed: ","未找到的工具可用上方「安装」按钮一键安装(":"Missing tools can be installed with the \"Install\" button above (","Windows 用 winget / 内置功能":"winget / built-in features on Windows","用系统包管理器":"your system package manager",",可能需管理员权限);也可手动复制安装命令执行,安装后点「重新检查」。":"; admin rights may be required). You can also copy the install command and run it manually, then click \"Re-check\".","重新检查":"Re-check",":已存在,无需重复操作":": already exists, no need to repeat","成功":" succeeded","失败":" failed","失败:":"Failed: ","平台":"Platform","选择代码托管平台:GitHub 或 Gitee(默认 GitHub),③代码管理会跟随切换":"Choose the code hosting platform: GitHub or Gitee (GitHub default); step ③ follows this switch","GitHub(默认)":"GitHub (default)","② SSH 密钥与连接":"② SSH Key & Connection","密钥":"Key"," 已生成":" generated","⚠️ 未生成":"⚠️ Not generated","GH 登录":"GH login","已登录":"Logged in","⚠️ 未登录":"⚠️ Not logged in","SSH 配置":"SSH config"," 已配置(443)":" configured (443)","⚠️ 未配置/限制 22 端口需配置":"⚠️ Not configured / port 22 blocked — use 443","生成密钥":"Generate key","配置 SSH(config)":"Configure SSH config","配置 SSH":"Configure SSH","测试连接":"Test connection","SSH 连接成功(":"SSH connection succeeded (","已认证":"authenticated","连接失败,请确认密钥已上传到 ":"Connection failed. Make sure the key is uploaded to "," 或已登录 gh":" or that gh is logged in","测试失败:":"Test failed: ","公钥(复制上传到 ":"Public key (copy and upload to ","Gitee → 设置 → SSH 公钥":"Gitee → Settings → SSH keys",",或运行 gh auth login 自动上传):":", or run gh auth login to upload it automatically):","该目录不是 git 仓库":"This folder is not a git repository","读取令牌状态失败:":"Failed to read token status: ","已保存 Gitee 令牌(账号:":"Gitee token saved (account: ","保存令牌失败":"Failed to save token","保存令牌失败:":"Failed to save token: ","已清除 Gitee 令牌":"Gitee token cleared","清除失败":"Clear failed","清除令牌失败:":"Failed to clear token: ","已推送":"Pushed","推送失败":"Push failed","推送失败:":"Push failed: ","已拉取远程更新(本地已对齐到远程最新状态)":"Pulled remote updates (local is now aligned with the latest remote state)","拉取失败":"Pull failed","拉取失败:":"Pull failed: ","已拉取远程更新并推送更改":"Pulled remote updates and pushed changes","合并推送失败":"Merge-push failed","合并推送失败:":"Merge-push failed: ","强制推送会用本地版本覆盖远程仓库,远程上非本地的更改将被丢弃。确定继续?":"Force-push overwrites the remote repo with your local version; remote-only changes will be lost. Continue?","已强制推送,远程已更新为本地状态":"Force-pushed; the remote is now your local state","强制推送失败":"Force-push failed","强制推送失败:":"Force-push failed: ","强制拉取会把远程更新并入本地。如果本地有不想保留的内容,将按冲突处理或遗失。确定继续?":"Force-pull merges remote updates into local; anything you don't want kept may conflict or be lost. Continue?","已强制拉取远程更新":"Force-pulled remote updates","强制拉取失败":"Force-pull failed","强制拉取失败:":"Force-pull failed: ","请先加载一个有效的文件夹":"Load a valid folder first","确定把仓库 ":"Change repo "," 改为「":" visibility to「","公开":"Public","私有":"Private","」?修改可见性可能影响 Star、关注者等。":"」? Changing visibility may affect stars, watchers, etc.","已把仓库设置为「":"Repo set to「","修改可见性失败":"Failed to change visibility","修改可见性失败:":"Failed to change visibility: ","仓库已创建并推送:":"Repo created and pushed: ","创建失败":"Create failed","创建失败:":"Create failed: ","未选择目录":"No folder selected","选择失败:":"Selection failed: ","请输入或选择目录路径":"Enter or pick a folder path","添加目录失败":"Failed to add folder","添加目录失败:":"Failed to add folder: ","删除失败":"Delete failed","删除失败:":"Delete failed: ","强制对齐会用远程分支覆盖本地(丢弃本地未推送的更改与提交),确定继续?":"Force-align overwrites local with the remote branch (drops unpushed local changes and commits). Continue?","已强制对齐到远程分支":"Force-aligned to the remote branch","强制对齐失败":"Force-align failed","强制对齐失败:":"Force-align failed: ","已是 git 仓库":"Already a git repository","已创建 git 仓库,请自行拉取或推送":"Git repository created — pull or push as you wish","创建 git 失败":"Failed to init git","创建 git 失败:":"Failed to init git: ","暂存失败":"Stage failed","暂存失败:":"Stage failed: ","取消暂存失败":"Unstage failed","取消暂存失败:":"Unstage failed: ","已提交 ":"Committed "," 个文件":" file(s)","提交失败":"Commit failed","提交失败:":"Commit failed: ","已提交「":"Committed「","(自动生成)":" (auto-generated)","」并推送":"」 and pushed","已推送本地已有的提交":"Pushed existing local commits","读取分支失败":"Failed to load branches","读取分支失败:":"Failed to load branches: ","切换到分支「":"Switch to branch「","」?(若当前有未提交改动,git 会拒绝切换)":"」? (git will refuse if you have uncommitted changes)","已切换到分支 ":"Switched to branch ","切换分支失败":"Failed to switch branch","切换分支失败:":"Failed to switch branch: ","读取历史失败":"Failed to load history","读取历史失败:":"Failed to load history: ","revert 提交「":"Revert commit「","」——会生成一个反向提交,期间可能产生冲突,确定继续?":"」 — this creates a reverse commit and may cause conflicts. Continue?","已 revert 提交 ":"Reverted commit ","revert 失败":"Revert failed","revert 失败:":"Revert failed: ","cherry-pick 提交「":"Cherry-pick commit「","」到当前分支——期间可能产生冲突,确定继续?":"」 onto the current branch — this may cause conflicts. Continue?","已 cherry-pick 提交 ":"Cherry-picked commit ","cherry-pick 失败":"Cherry-pick failed","cherry-pick 失败:":"Cherry-pick failed: ","读取失败":"Failed to load","已复制":"Copied","短哈希":"short hash","完整哈希":"full hash","提交信息":"commit message","复制失败:请手动复制":"Copy failed — copy it manually","③ 代码管理":"③ Code Management","Gitee 私人令牌(OpenAPI,需 projects 权限)":"Gitee personal token (OpenAPI, requires projects permission)","✅ 已配置":"✅ Configured","(账号 ":" (account ","清除令牌":"Clear token","粘贴 Gitee 私人令牌(https://gitee.com/personal_access_tokens)":"Paste the Gitee personal token (https://gitee.com/personal_access_tokens)","保存令牌":"Save token","令牌只保存在本机 ~/.dsh/storages(0600),不会写进插件目录;需勾选个人令牌的 projects 权限。公钥需已上传到 Gitee(② 里检查)。":"The token is stored only on this machine at ~/.dsh/storages (0600), never in the plugin directory; the personal token must have projects permission. Your public key must be uploaded to Gitee (checked in ②).","选择工作区":"Workspace","选择 DSH 已登记的工作区文件夹":"Choose a workspace folder registered in DSH","(暂无可选工作区)":"(no workspaces available)","— 请选择 —":"— Select —","选择目录":"Choose folder","自定义目录:":"Custom folder: ","删除该目录记录":"Remove this folder entry","删除该目录记录(不删除实际文件夹)":"Remove this folder entry (does not delete the actual folder)","目录":"Folder","分支":"Branch","(无)":"(none)","切换分支":"Switch branch","切换":"Switch","查看提交历史":"View commit history","历史":"History","远程":"Remote","改动":"Changes","无":"None","查看改动的文件列表":"View the list of changed files","查看":"View","同步":"Sync","本地领先 ":"Ahead by "," 提交":" commit(s)","、落后 ":", behind by ","落后 ":"behind by ","与远程一致":"Up to date with remote","查看本地与远程的提交差异":"View commit differences between local and remote","⚠️ 以下 ":"⚠️ The following "," 项 >100MB(超过 GitHub 限制,推送时将自动忽略不上传):":" item(s) >100MB (over GitHub's limit — auto-ignored on push):","/(整个文件夹)":"/ (entire folder)","创建 Git":"Init Git","仅初始化 git 仓库,不拉取不推送,由你决定下一步":"Initializes a git repo only — no pull/push; you decide the next step","本地有改动且远程有更新,可直接用「强制对齐」将本地重置为远程状态":"You have local changes AND remote updates — use \"Force align\" to reset local to the remote state","强制对齐":"Force align","本地完全重置为远程分支(丢弃本地差异),解决“文件相同仍显示同步差异”的情况":"Fully resets local to the remote branch (drops local differences); fixes \"files identical but sync still shows a difference\"","推送更改":"Push changes","拉取更新":"Pull updates","✓ 已是最新":"✓ Up to date","⟳ 正在刷新状态,联网同步 GitHub/Gitee 最新数据…":"⟳ Refreshing status — syncing the latest GitHub/Gitee data…","⟳ 切换平台,正在重新检测「":"⟳ Switching platform, re-checking「","」仓库状态…":"」 repo status…","推送中…":"Pushing…","推送暂存":"Push staged","把已暂存的内容用填写的(或自动生成的)信息提交后推送到远程;不会自动暂存其他未暂存的改动":"Commits only what is staged (with your message, or auto-generated) and pushes it; does not auto-stage other changes","刷新中…":"Refreshing…","刷新状态":"Refresh status","提交信息(留空则用默认)":"Commit message (default if empty)","填写提交信息后点「提交」;留空则自动生成(chore: update <文件夹名>)":"Type a message then click \"Commit\"; leave empty to auto-generate (chore: update <folder>)","提交":"Commit","仓库名称自动取文件夹名(不可修改)":"Repo name is taken from the folder name (read-only)","(未加载文件夹)":"(no folder loaded)","仓库可见性:私有 / 公开":"Repo visibility: private / public","(修改当前仓库的可见性)":" (changes the current repo's visibility)","新建仓库并推送":"Create repo & push","修改仓库状态":"Change repo status","✓ 仓库已是「":"✓ Repo is already「","」状态,如需修改请调整左侧可见性选择。":"」 — to change it, adjust the visibility dropdown.","将把仓库从「":"Will change the repo from「","」改为「":"」 to「","」,点击「修改仓库状态」执行。":"」 — click \"Change repo status\" to apply.","⚠️ 同名仓库已经创建(无法读取当前可见性,可能未":"⚠️ A repo with this name already exists (couldn't read its visibility — maybe not ","配置 Gitee 令牌":"Gitee token configured","登录 gh":"logged into gh","✓ 同名仓库 ":"✓ No repo named "," 不存在,可在 ":" exists — you can create it on ","「新建仓库并推送」创建(可选私有/公开)。":" with \"Create repo & push\" (private or public).","已忽略未上传(":"Skipped uploads ("," 项 >100MB):":" item(s) >100MB):","已提交":"Committed"," 并推送":" and pushed","(推送省略)":" (push skipped)","查看详情":"View details","改动文件":"Changed files","提交历史":"Commit history","与远程同步差异":"Sync differences vs remote","关闭":"Close","已安装 dsh-better-sidebar,此处只列改动文件列表;具体改动内容请到 dsh-better-sidebar 的「源代码管理 / Git 面板」查看。":"dsh-better-sidebar is installed — this lists changed files only; see the actual changes in its \"Source Control / Git\" panel.","点击收起":"Click to collapse","点击查看改动内容":"Click to view the diff","新文件(untracked)暂无内容 diff":"New (untracked) file — no diff yet","已暂存":"Staged","未暂存":"Unstaged","取消暂存":"Unstage","暂存":"Stage","加载中…":"Loading…","▾ 收起":"▾ Collapse","▸ 查看":"▸ View","正在加载改动内容…":"Loading changes…","(无内容差异)":"(no diff)","当前没有改动。":"No changes.","正在读取分支…":"Loading branches…","(无分支)":"(no branches)","(当前)":"(current)","正在读取历史…":"Loading history…","(暂无提交)":"(no commits)","更多操作(右键也可打开)":"More actions (right-click also works)","查看提交差异":"View commit diff","复制短哈希":"Copy short hash","复制完整哈希":"Copy full hash","复制提交信息":"Copy commit message","还原此提交":"Revert this commit","拾取此提交":"Cherry-pick this commit","正在加载提交 diff…":"Loading commit diff…","本地落后 ":"Behind by "," 个提交(远程有而本地没有):":" commit(s) (on remote, not local):"," 个提交(本地有而远程没有):":" commit(s) (on local, not remote):","✓ 已与远程同步,无差异。":"✓ In sync with remote — no differences.","选择代码目录":"Choose a code folder","可手动输入/粘贴目录绝对路径,或点击「浏览…」弹出本地文件夹选择器。确认后将添加到下方下拉并记住,下次打开无需重新选择。":"Paste an absolute folder path, or click \"Browse…\" for the native picker. Confirmed folders are added to the dropdown and remembered.","C:\\Users\\你的用户名\\项目目录":"C:\\Users\\your-name\\project","浏览…":"Browse…","取消":"Cancel","确定":"OK","新增":"Added","删除":"Deleted","重命名":"Renamed","修改":"Modified","旧版本":"Old","新版本":"New","源代码管理":"Source Control","按顺序完成:①环境检查 → ②SSH 密钥与连接 → ③代码管理。推送会自动忽略 >100MB 的文件(":"Work through in order: ① Environment → ② SSH Key & Connection → ③ Code Management. Files over 100MB are auto-ignored on push ("," 限制)并说明原因。":" limit) with the reason shown.","代码管理":"Code Management","拖动调整面板宽度":"Drag to resize the panel"};
|
|
182
|
+
const EN_DICT = {"展开":"Expand","折叠":"Collapse","展开该部分":"Expand this section","折叠该部分":"Collapse this section","已安装":"Installed","❌ 未安装":"❌ Not installed","复制安装命令":"Copy install command","一键安装(会自动选包管理器)":"Install automatically (picks a package manager)","安装中…":"Installing…","安装":"Install"," 执行成功":" executed successfully","(如未生效需以管理员身份重试)":" (retry as administrator if it did not take effect)","安装失败":"Install failed","① 环境检查":"① Environment","✅ 均存在":"✅ All present","操作系统":"OS","已找到":"Found","检测中":"Checking","失败: ":"Failed: ","未找到的工具可用上方「安装」按钮一键安装(":"Missing tools can be installed with the \"Install\" button above (","Windows 用 winget / 内置功能":"winget / built-in features on Windows","用系统包管理器":"your system package manager",",可能需管理员权限);也可手动复制安装命令执行,安装后点「重新检查」。":"; admin rights may be required). You can also copy the install command and run it manually, then click \"Re-check\".","重新检查":"Re-check",":已存在,无需重复操作":": already exists, no need to repeat","成功":" succeeded","失败":" failed","失败:":"Failed: ","平台":"Platform","选择代码托管平台:GitHub 或 Gitee(默认 GitHub),③代码管理会跟随切换":"Choose the code hosting platform: GitHub or Gitee (GitHub default); step ③ follows this switch","GitHub(默认)":"GitHub (default)","② SSH 密钥与连接":"② SSH Key & Connection","密钥":"Key"," 已生成":" generated","⚠️ 未生成":"⚠️ Not generated","GH 登录":"GH login","已登录":"Logged in","⚠️ 未登录":"⚠️ Not logged in","SSH 配置":"SSH config"," 已配置(443)":" configured (443)","⚠️ 未配置/限制 22 端口需配置":"⚠️ Not configured / port 22 blocked — use 443","生成密钥":"Generate key","配置 SSH(config)":"Configure SSH config","配置 SSH":"Configure SSH","测试连接":"Test connection","SSH 连接成功(":"SSH connection succeeded (","已认证":"authenticated","连接失败,请确认密钥已上传到 ":"Connection failed. Make sure the key is uploaded to "," 或已登录 gh":" or that gh is logged in","测试失败:":"Test failed: ","公钥(复制上传到 ":"Public key (copy and upload to ","Gitee → 设置 → SSH 公钥":"Gitee → Settings → SSH keys",",或运行 gh auth login 自动上传):":", or run gh auth login to upload it automatically):","该目录不是 git 仓库":"This folder is not a git repository","读取令牌状态失败:":"Failed to read token status: ","已保存 Gitee 令牌(账号:":"Gitee token saved (account: ","保存令牌失败":"Failed to save token","保存令牌失败:":"Failed to save token: ","已清除 Gitee 令牌":"Gitee token cleared","清除失败":"Clear failed","清除令牌失败:":"Failed to clear token: ","已推送":"Pushed","推送失败":"Push failed","推送失败:":"Push failed: ","已拉取远程更新(本地已对齐到远程最新状态)":"Pulled remote updates (local is now aligned with the latest remote state)","拉取失败":"Pull failed","拉取失败:":"Pull failed: ","已拉取远程更新并推送更改":"Pulled remote updates and pushed changes","合并推送失败":"Merge-push failed","合并推送失败:":"Merge-push failed: ","强制推送会用本地版本覆盖远程仓库,远程上非本地的更改将被丢弃。确定继续?":"Force-push overwrites the remote repo with your local version; remote-only changes will be lost. Continue?","已强制推送,远程已更新为本地状态":"Force-pushed; the remote is now your local state","强制推送失败":"Force-push failed","强制推送失败:":"Force-push failed: ","强制拉取会把远程更新并入本地。如果本地有不想保留的内容,将按冲突处理或遗失。确定继续?":"Force-pull merges remote updates into local; anything you don't want kept may conflict or be lost. Continue?","已强制拉取远程更新":"Force-pulled remote updates","强制拉取失败":"Force-pull failed","强制拉取失败:":"Force-pull failed: ","请先加载一个有效的文件夹":"Load a valid folder first","确定把仓库 ":"Change repo "," 改为「":" visibility to「","公开":"Public","私有":"Private","」?修改可见性可能影响 Star、关注者等。":"」? Changing visibility may affect stars, watchers, etc.","已把仓库设置为「":"Repo set to「","修改可见性失败":"Failed to change visibility","修改可见性失败:":"Failed to change visibility: ","仓库已创建并推送:":"Repo created and pushed: ","创建失败":"Create failed","创建失败:":"Create failed: ","未选择目录":"No folder selected","选择失败:":"Selection failed: ","请输入或选择目录路径":"Enter or pick a folder path","添加目录失败":"Failed to add folder","添加目录失败:":"Failed to add folder: ","删除失败":"Delete failed","删除失败:":"Delete failed: ","强制对齐会用远程分支覆盖本地(丢弃本地未推送的更改与提交),确定继续?":"Force-align overwrites local with the remote branch (drops unpushed local changes and commits). Continue?","已强制对齐到远程分支":"Force-aligned to the remote branch","强制对齐失败":"Force-align failed","强制对齐失败:":"Force-align failed: ","已是 git 仓库":"Already a git repository","已创建 git 仓库,请自行拉取或推送":"Git repository created — pull or push as you wish","创建 git 失败":"Failed to init git","创建 git 失败:":"Failed to init git: ","暂存失败":"Stage failed","暂存失败:":"Stage failed: ","取消暂存失败":"Unstage failed","取消暂存失败:":"Unstage failed: ","已提交 ":"Committed "," 个文件":" file(s)","提交失败":"Commit failed","提交失败:":"Commit failed: ","已提交「":"Committed「","(自动生成)":" (auto-generated)","」并推送":"」 and pushed","已推送本地已有的提交":"Pushed existing local commits","读取分支失败":"Failed to load branches","读取分支失败:":"Failed to load branches: ","切换到分支「":"Switch to branch「","」?(若当前有未提交改动,git 会拒绝切换)":"」? (git will refuse if you have uncommitted changes)","已切换到分支 ":"Switched to branch ","切换分支失败":"Failed to switch branch","切换分支失败:":"Failed to switch branch: ","读取历史失败":"Failed to load history","读取历史失败:":"Failed to load history: ","revert 提交「":"Revert commit「","」——会生成一个反向提交,期间可能产生冲突,确定继续?":"」 — this creates a reverse commit and may cause conflicts. Continue?","已 revert 提交 ":"Reverted commit ","revert 失败":"Revert failed","revert 失败:":"Revert failed: ","cherry-pick 提交「":"Cherry-pick commit「","」到当前分支——期间可能产生冲突,确定继续?":"」 onto the current branch — this may cause conflicts. Continue?","已 cherry-pick 提交 ":"Cherry-picked commit ","cherry-pick 失败":"Cherry-pick failed","cherry-pick 失败:":"Cherry-pick failed: ","读取失败":"Failed to load","已复制":"Copied","短哈希":"short hash","完整哈希":"full hash","提交信息":"commit message","复制失败:请手动复制":"Copy failed — copy it manually","③ 代码管理":"③ Code Management","Gitee 私人令牌(OpenAPI,需 projects 权限)":"Gitee personal token (OpenAPI, requires projects permission)","✅ 已配置":"✅ Configured","(账号 ":" (account ","清除令牌":"Clear token","粘贴 Gitee 私人令牌(https://gitee.com/personal_access_tokens)":"Paste the Gitee personal token (https://gitee.com/personal_access_tokens)","保存令牌":"Save token","令牌只保存在本机 ~/.dsh/storages(0600),不会写进插件目录;需勾选个人令牌的 projects 权限。公钥需已上传到 Gitee(② 里检查)。":"The token is stored only on this machine at ~/.dsh/storages (0600), never in the plugin directory; the personal token must have projects permission. Your public key must be uploaded to Gitee (checked in ②).","选择工作区":"Workspace","选择 DSH 已登记的工作区文件夹":"Choose a workspace folder registered in DSH","(暂无可选工作区)":"(no workspaces available)","— 请选择 —":"— Select —","选择目录":"Choose folder","自定义目录:":"Custom folder: ","删除该目录记录":"Remove this folder entry","删除该目录记录(不删除实际文件夹)":"Remove this folder entry (does not delete the actual folder)","目录":"Folder","分支":"Branch","(无)":"(none)","切换分支":"Switch branch","切换":"Switch","查看提交历史":"View commit history","历史":"History","远程":"Remote","改动":"Changes","无":"None","查看改动的文件列表":"View the list of changed files","查看":"View","同步":"Sync","本地领先 ":"Ahead by "," 提交":" commit(s)","、落后 ":", behind by ","落后 ":"behind by ","与远程一致":"Up to date with remote","查看本地与远程的提交差异":"View commit differences between local and remote","⚠️ 以下 ":"⚠️ The following "," 项 >100MB(超过 GitHub 限制,推送时将自动忽略不上传):":" item(s) >100MB (over GitHub's limit — auto-ignored on push):","/(整个文件夹)":"/ (entire folder)","创建 Git":"Init Git","仅初始化 git 仓库,不拉取不推送,由你决定下一步":"Initializes a git repo only — no pull/push; you decide the next step","本地有改动且远程有更新,可直接用「强制对齐」将本地重置为远程状态":"You have local changes AND remote updates — use \"Force align\" to reset local to the remote state","强制对齐":"Force align","本地完全重置为远程分支(丢弃本地差异),解决“文件相同仍显示同步差异”的情况":"Fully resets local to the remote branch (drops local differences); fixes \"files identical but sync still shows a difference\"","推送更改":"Push changes","拉取更新":"Pull updates","✓ 已是最新":"✓ Up to date","⟳ 正在刷新状态,联网同步 GitHub/Gitee 最新数据…":"⟳ Refreshing status — syncing the latest GitHub/Gitee data…","⟳ 切换平台,正在重新检测「":"⟳ Switching platform, re-checking「","」仓库状态…":"」 repo status…","推送中…":"Pushing…","推送暂存":"Push staged","把已暂存的内容用填写的(或自动生成的)信息提交后推送到远程;不会自动暂存其他未暂存的改动":"Commits only what is staged (with your message, or auto-generated) and pushes it; does not auto-stage other changes","刷新中…":"Refreshing…","刷新状态":"Refresh status","提交信息(留空则用默认)":"Commit message (default if empty)","填写提交信息后点「提交」;留空则自动生成(chore: update <文件夹名>)":"Type a message then click \"Commit\"; leave empty to auto-generate (chore: update <folder>)","提交":"Commit","仓库名称自动取文件夹名(不可修改)":"Repo name is taken from the folder name (read-only)","(未加载文件夹)":"(no folder loaded)","仓库可见性:私有 / 公开":"Repo visibility: private / public","(修改当前仓库的可见性)":" (changes the current repo's visibility)","新建仓库并推送":"Create repo & push","修改仓库状态":"Change repo status","✓ 仓库已是「":"✓ Repo is already「","」状态,如需修改请调整左侧可见性选择。":"」 — to change it, adjust the visibility dropdown.","将把仓库从「":"Will change the repo from「","」改为「":"」 to「","」,点击「修改仓库状态」执行。":"」 — click \"Change repo status\" to apply.","⚠️ 同名仓库已经创建(无法读取当前可见性,可能未":"⚠️ A repo with this name already exists (couldn't read its visibility — maybe not ","配置 Gitee 令牌":"Gitee token configured","登录 gh":"logged into gh","✓ 同名仓库 ":"✓ No repo named "," 不存在,可在 ":" exists — you can create it on ","「新建仓库并推送」创建(可选私有/公开)。":" with \"Create repo & push\" (private or public).","已忽略未上传(":"Skipped uploads ("," 项 >100MB):":" item(s) >100MB):","已提交":"Committed"," 并推送":" and pushed","(推送省略)":" (push skipped)","查看详情":"View details","改动文件":"Changed files","提交历史":"Commit history","与远程同步差异":"Sync differences vs remote","关闭":"Close","已安装 dsh-better-sidebar,此处只列改动文件列表;具体改动内容请到 dsh-better-sidebar 的「源代码管理面板」查看。":"dsh-better-sidebar is installed — this lists changed files only; see the actual changes in its \"Source Control panel\".","点击收起":"Click to collapse","点击查看改动内容":"Click to view the diff","新文件(untracked)暂无内容 diff":"New (untracked) file — no diff yet","已暂存":"Staged","未暂存":"Unstaged","取消暂存":"Unstage","暂存":"Stage","加载中…":"Loading…","▾ 收起":"▾ Collapse","▸ 查看":"▸ View","正在加载改动内容…":"Loading changes…","(无内容差异)":"(no diff)","当前没有改动。":"No changes.","正在读取分支…":"Loading branches…","(无分支)":"(no branches)","(当前)":"(current)","正在读取历史…":"Loading history…","(暂无提交)":"(no commits)","更多操作(右键也可打开)":"More actions (right-click also works)","查看提交差异":"View commit diff","复制短哈希":"Copy short hash","复制完整哈希":"Copy full hash","复制提交信息":"Copy commit message","还原此提交":"Revert this commit","拾取此提交":"Cherry-pick this commit","正在加载提交 diff…":"Loading commit diff…","本地落后 ":"Behind by "," 个提交(远程有而本地没有):":" commit(s) (on remote, not local):"," 个提交(本地有而远程没有):":" commit(s) (on local, not remote):","✓ 已与远程同步,无差异。":"✓ In sync with remote — no differences.","选择代码目录":"Choose a code folder","可手动输入/粘贴目录绝对路径,或点击「浏览…」弹出本地文件夹选择器。确认后将添加到下方下拉并记住,下次打开无需重新选择。":"Paste an absolute folder path, or click \"Browse…\" for the native picker. Confirmed folders are added to the dropdown and remembered.","C:\\Users\\你的用户名\\项目目录":"C:\\Users\\your-name\\project","浏览…":"Browse…","取消":"Cancel","确定":"OK","新增":"Added","删除":"Deleted","重命名":"Renamed","修改":"Modified","旧版本":"Old","新版本":"New","源代码管理":"Source Control","按顺序完成:①环境检查 → ②SSH 密钥与连接 → ③代码管理。推送会自动忽略 >100MB 的文件(":"Work through in order: ① Environment → ② SSH Key & Connection → ③ Code Management. Files over 100MB are auto-ignored on push ("," 限制)并说明原因。":" limit) with the reason shown.","代码管理":"Code Management","拖动调整面板宽度":"Drag to resize the panel"};
|
|
183
183
|
let scmLang = (() => { try { return String(navigator.language || "zh").toLowerCase().split("-")[0] === "en" ? "en" : "zh" } catch { return "zh" } })();
|
|
184
184
|
let scmLocaleFace = null; // ctx.locale (the DSH LocaleRuntime), set in apply()
|
|
185
|
+
let scmSessionList = null; // ctx.get('sessions').list (ObservableSnapshot), set in apply() — 用于判断「无会话空态」
|
|
185
186
|
function currentLang() { try { if (scmLocaleFace && typeof scmLocaleFace.getLocale === "function") return scmLocaleFace.getLocale().active } catch {} return scmLang }
|
|
186
187
|
function t(key, params) {
|
|
187
188
|
let s = key;
|
|
@@ -202,6 +203,18 @@ function useLocale() {
|
|
|
202
203
|
}, [scmLocaleFace]);
|
|
203
204
|
}
|
|
204
205
|
|
|
206
|
+
/** Re-render when the session list changes(新增/切换/清空会话)。用于空态常驻按钮判断:
|
|
207
|
+
* 读到 current === undefined 即「当前没有会话」。 */
|
|
208
|
+
function useSession() {
|
|
209
|
+
const [, force] = useState(0);
|
|
210
|
+
useEffect(() => {
|
|
211
|
+
if (!scmSessionList || typeof scmSessionList.subscribe !== "function") return;
|
|
212
|
+
const off = scmSessionList.subscribe(() => force((n) => n + 1));
|
|
213
|
+
force((n) => n + 1);
|
|
214
|
+
return off;
|
|
215
|
+
}, [scmSessionList]);
|
|
216
|
+
}
|
|
217
|
+
|
|
205
218
|
|
|
206
219
|
function Field({ label, value, children }) {
|
|
207
220
|
return h("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 6 } },
|
|
@@ -1269,7 +1282,7 @@ function useLocale() {
|
|
|
1269
1282
|
h("div", { style: { flex: 1, overflow: "auto" } },
|
|
1270
1283
|
detail === "changes" ? h(React.Fragment, null,
|
|
1271
1284
|
hasBetterSidebar ? h("div", { style: { marginBottom: 10, padding: "8px 10px", borderRadius: 8, background: T.layer1, color: T.secondary, fontSize: 12, lineHeight: 1.6 } },
|
|
1272
|
-
t("已安装 dsh-better-sidebar,此处只列改动文件列表;具体改动内容请到 dsh-better-sidebar
|
|
1285
|
+
t("已安装 dsh-better-sidebar,此处只列改动文件列表;具体改动内容请到 dsh-better-sidebar 的「源代码管理面板」查看。"))
|
|
1273
1286
|
: null,
|
|
1274
1287
|
repo && repo.changedFiles && repo.changedFiles.length > 0
|
|
1275
1288
|
? repo.changedFiles.map((f, i) => {
|
|
@@ -1778,6 +1791,25 @@ function useLocale() {
|
|
|
1778
1791
|
);
|
|
1779
1792
|
}
|
|
1780
1793
|
|
|
1794
|
+
/** 空态(无会话)时的常驻右上角入口:注册进常驻的 shell.overlay 槽,用 fixed 钉在
|
|
1795
|
+
* 视口右上角。仅当「当前没有会话」(sessionList.current === undefined)时显示——
|
|
1796
|
+
* 有会话时交给 header utilities 按钮,避免两处重复。点击复用 HeaderScmAction 打开面板。 */
|
|
1797
|
+
function EmptyStateScmAction() {
|
|
1798
|
+
useSession();
|
|
1799
|
+
const snap = scmSessionList && typeof scmSessionList.getSnapshot === "function" ? scmSessionList.getSnapshot() : undefined;
|
|
1800
|
+
// 尚未捕获到 sessions 时先不渲染:避免刷新瞬间(captureSessions 的 1.2s 延迟窗口内)
|
|
1801
|
+
// 因 scmSessionList 为 null 而错误点亮常驻按钮、与「Session 日志」重叠。
|
|
1802
|
+
if (!snap) return null;
|
|
1803
|
+
const current = snap.current;
|
|
1804
|
+
const cur = current !== undefined ? (snap.byId ? snap.byId[current] : undefined) : undefined;
|
|
1805
|
+
// 活跃(非空白)会话 → header 里已有「代码管理」按钮(会话内);这里隐藏常驻按钮。
|
|
1806
|
+
// 空白(新对话/欢迎)或根本没有会话 → header 被 hideChrome 隐藏/不存在,显示常驻右上角按钮。
|
|
1807
|
+
const hasActiveSession = current !== undefined && cur && cur.blank === false;
|
|
1808
|
+
if (hasActiveSession) return null;
|
|
1809
|
+
return h("div", { style: { position: "fixed", top: 8, right: 12, zIndex: 40, pointerEvents: "auto" } },
|
|
1810
|
+
h(HeaderScmAction));
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1781
1813
|
/** 挂载一个经典脚本 React 根(React 18 用 createRoot,老版本回退 render)。 */
|
|
1782
1814
|
function mountClientRoot(container, element) {
|
|
1783
1815
|
try {
|
|
@@ -1833,6 +1865,23 @@ function useLocale() {
|
|
|
1833
1865
|
}, 1200);
|
|
1834
1866
|
}
|
|
1835
1867
|
|
|
1868
|
+
// 捕获 `sessions.list`(用于「是否无会话」判断)。sessions 是核心服务、通常早于本插件
|
|
1869
|
+
// 就绪;若还没就绪,单次延迟补抓一次(组件经 useSession 订阅后会自动重渲染)。
|
|
1870
|
+
const captureSessions = () => {
|
|
1871
|
+
try {
|
|
1872
|
+
if (scmSessionList) return true;
|
|
1873
|
+
const s = ctx && typeof ctx.get === "function" ? ctx.get("sessions") : undefined;
|
|
1874
|
+
if (s && typeof s.list === "object" && s.list) {
|
|
1875
|
+
scmSessionList = s.list;
|
|
1876
|
+
return true;
|
|
1877
|
+
}
|
|
1878
|
+
return false;
|
|
1879
|
+
} catch { return false }
|
|
1880
|
+
};
|
|
1881
|
+
if (!captureSessions()) {
|
|
1882
|
+
window.setTimeout(() => { captureSessions(); }, 1200);
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1836
1885
|
// DSH 打开(插件激活)时就预取环境/SSH/默认工作区/仓库状态,
|
|
1837
1886
|
// 点开「代码管理」面板时直接使用缓存,无需重新加载。
|
|
1838
1887
|
void preload();
|
|
@@ -1844,7 +1893,9 @@ function useLocale() {
|
|
|
1844
1893
|
|
|
1845
1894
|
const tryRegisterTab = () => {
|
|
1846
1895
|
const bs = typeof ctx.get === "function" ? ctx.get("betterSidebar") : undefined;
|
|
1847
|
-
if (!bs || typeof bs.registerTab !== "function")
|
|
1896
|
+
if (!bs || typeof bs.registerTab !== "function") {
|
|
1897
|
+
return false;
|
|
1898
|
+
}
|
|
1848
1899
|
// 分支 A:已安装 dsh-better-sidebar —— 把「代码管理」注册成它的侧边栏新 Tab
|
|
1849
1900
|
// 页面。ctx.effect 保证 HMR / 插件卸载时自动注销该 Tab。
|
|
1850
1901
|
hasBetterSidebar = true;
|
|
@@ -1880,17 +1931,38 @@ function useLocale() {
|
|
|
1880
1931
|
|
|
1881
1932
|
if (tryRegisterTab()) return;
|
|
1882
1933
|
|
|
1883
|
-
// 分支 B:此刻未检测到 dsh-better-sidebar ——
|
|
1884
|
-
// conversation.session.header.utilities
|
|
1885
|
-
//
|
|
1886
|
-
//
|
|
1934
|
+
// 分支 B:此刻未检测到 dsh-better-sidebar —— 注册两处「代码管理」入口,保证右上角常驻可见:
|
|
1935
|
+
// ① 有会话时:放进 conversation.session.header.utilities(Session 日志旁的右对齐列表);
|
|
1936
|
+
// ② 无会话空态时:放进常驻的 shell.overlay 槽、用 fixed 钉在右上角(EmptyStateScmAction
|
|
1937
|
+
// 内部按「是否有当前会话」决定显隐,有会话时返回 null,避免与 ① 重复)。
|
|
1938
|
+
// 点击都复用 HeaderScmAction 打开右侧 dsh-better-sidebar 外观的集成面板(推挤 #root)。
|
|
1887
1939
|
const slots = typeof ctx.get === "function" ? ctx.get("slots") : undefined;
|
|
1888
1940
|
if (slots && typeof slots.inject === "function") {
|
|
1889
|
-
ctx.effect(() =>
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1941
|
+
ctx.effect(() => {
|
|
1942
|
+
const teardowns = [];
|
|
1943
|
+
// ① 会话内:Session 日志旁
|
|
1944
|
+
teardowns.push(slots.inject('conversation.session.header.utilities', () => slots.register({
|
|
1945
|
+
name: 'conversation.session.header.utilities',
|
|
1946
|
+
id: 'source-code-mgmt',
|
|
1947
|
+
order: 200,
|
|
1948
|
+
}, HeaderScmAction)));
|
|
1949
|
+
// ② 空态:常驻右上角(仅无会话时显示)
|
|
1950
|
+
teardowns.push(slots.inject('shell.overlay', () => slots.register({
|
|
1951
|
+
name: 'shell.overlay',
|
|
1952
|
+
id: 'source-code-mgmt-empty',
|
|
1953
|
+
order: 300,
|
|
1954
|
+
}, EmptyStateScmAction)));
|
|
1955
|
+
// entryUnmount 一次性拆掉两处:这样当之后探测到 better-sidebar、切到分支 A
|
|
1956
|
+
// (注册 Tab)时,tryRegisterTab 里的 entryUnmount() 能把两处入口都移除。
|
|
1957
|
+
// (旧代码只给 ReactDOM 降级路径设了 entryUnmount,slots 路径漏了 —— 这正是
|
|
1958
|
+
// 「better-sidebar 已出来、代码管理按钮却仍在」的早期根因。)
|
|
1959
|
+
entryUnmount = () => {
|
|
1960
|
+
for (const td of teardowns) { try { if (typeof td === "function") td() } catch {} }
|
|
1961
|
+
teardowns.length = 0;
|
|
1962
|
+
entryUnmount = null;
|
|
1963
|
+
};
|
|
1964
|
+
return entryUnmount;
|
|
1965
|
+
}, 'source-code-mgmt: entry (session header + empty overlay)');
|
|
1894
1966
|
} else if (ReactDOM) {
|
|
1895
1967
|
// slots 服务不可用(极少数环境)——降级:右上角浮动按钮 + 右侧面板。
|
|
1896
1968
|
ctx.effect(() => {
|
|
@@ -1906,10 +1978,26 @@ function useLocale() {
|
|
|
1906
1978
|
});
|
|
1907
1979
|
}
|
|
1908
1980
|
|
|
1909
|
-
//
|
|
1910
|
-
//
|
|
1911
|
-
|
|
1912
|
-
|
|
1981
|
+
// 有界重试:作为安全网,兜住 better-sidebar 的客户端服务晚于本插件挂载的情况
|
|
1982
|
+
// (两插件互不注入、加载器不保证顺序;其客户端 bundle 是重插件,偶发冷启动慢)。
|
|
1983
|
+
// 单次 1.5s 窗口不够,这里先用快节奏起步、再放慢,覆盖到约 44s;一旦拿到服务
|
|
1984
|
+
// (tryRegisterTab 返回 true)立即注册 Tab、拆除 header 入口并清空所有定时器;
|
|
1985
|
+
// 全程零 I/O(纯内存 ctx.get)。窗口耗尽仍无服务则停留分支 B(此时才是真正未安装)。
|
|
1986
|
+
const retryTimers = new Set();
|
|
1987
|
+
const retryTicks = [500, 500, 750, 1000, 1500, 2000, 3000, 5000, 5000, 5000, 5000, 5000, 5000, 5000];
|
|
1988
|
+
const clearRetry = () => {
|
|
1989
|
+
for (const timerId of retryTimers) { try { window.clearTimeout(timerId); } catch {} }
|
|
1990
|
+
retryTimers.clear();
|
|
1991
|
+
};
|
|
1992
|
+
for (const d of retryTicks) {
|
|
1993
|
+
const handle = window.setTimeout(() => {
|
|
1994
|
+
retryTimers.delete(handle);
|
|
1995
|
+
if (hasBetterSidebar) return;
|
|
1996
|
+
if (tryRegisterTab()) clearRetry();
|
|
1997
|
+
}, d);
|
|
1998
|
+
retryTimers.add(handle);
|
|
1999
|
+
}
|
|
2000
|
+
ctx.effect(() => clearRetry);
|
|
1913
2001
|
}
|
|
1914
2002
|
|
|
1915
2003
|
exports.name = PLUGIN_ID;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "source-code-mgmt",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.1",
|
|
4
4
|
"description": "DSH plugin: source code management. Registers「代码管理」as a dsh-better-sidebar sidebar Tab when installed, otherwise a button in the DSH session header's right-aligned utilities (beside \"Session log\") opening a right-side integrated panel that pushes the main content — env checks (git/gh), SSH ed25519 key setup, GitHub/Gitee dual-platform (SSH config 443 + Gitee OpenAPI), connectivity test, push / new repo, and auto-ignore files over 100MB with per-file skipped reasons. Cross-platform (Windows / Linux / macOS).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|