Skip to content

Releases: btsd321/dsh-oh-my-terminal

v0.4.7:修复 Ctrl+Shift+V 粘贴两次 / Fix Ctrl+Shift+V pasting text twice

Choose a tag to compare

@btsd321 btsd321 released this 28 Oct 10:48

中文

修复

  • 🔴 Ctrl+Shift+V 粘贴两次(本地直连 SSH 场景):v0.4.7 初版的标志方案有根本性时序缺陷——readText() 是异步的,但原生 paste 事件在 keydown 后同步触发,标志永远来不及在原生 paste 之前设置,导致本地直连 SSH 场景仍然双发。改用原生 paste 优先方案(反转去重方向):不再用异步 readText 结果去压制同步的原生 paste,而是用同步的原生 paste 决定之后要不要做 readText。
    • v 分支不调 preventDefault、不同步调 readText——让原生 paste 优先(Chromium Win/Linux 在 keydown 默认处理中同步派发 paste,由 xterm handlePasteEvent 单发,无需剪贴板权限)
    • keydown 时清零 nativePasteObserved,setTimeout(0) 延迟到宏任务检查:原生 paste 已发生 → 跳过 readText(单发);未发生(macOS 不映射该组合键)→ readText 兜底
    • onNativePaste 从拦截者变为纯观察者,不再调 preventDefault / stopImmediatePropagation
    • Electron webview(readText 被权限拒绝)→ 原生 paste 单发,不再触发权限 reject
  • 🟢 同时修复 Electron webview 下 Ctrl+Shift+V 完全无法粘贴:v0.4.6 的 preventDefault() 方案在 readText 失败时无法撤销阻断,导致 webview 下彻底无法粘贴。原生 paste 优先方案不调 preventDefault,webview 下原生 paste 正常触发单发。

验证

  • 类型检查(pnpm run typecheck)与构建(pnpm run build)均通过。
  • 在本地 Chrome 直连 DSH + SSH 到 BJ-SF-Robot 场景下按 Ctrl+Shift+V 确认只粘贴一次。
  • 在 dsh-remote-explorer 经 webview 远程 WSL 场景下按 Ctrl+Shift+V 确认能粘贴(原生 paste 兜底)。
  • 无配置项、API 或协议变更,升级后刷新页面即生效。

English

Fixes

  • 🔴 Ctrl+Shift+V pasted text twice (local direct SSH): The initial v0.4.7 flag-based approach had a fundamental timing flaw — readText() is async, but the native paste event fires synchronously after keydown, so the flag could never be set before the native paste arrived, causing double-paste in local direct SSH scenarios. Switched to a native-paste-first approach (reversing the dedup direction): instead of using the async readText result to suppress the synchronous native paste, use the synchronous native paste to decide whether to call readText at all.
    • The v branch no longer calls preventDefault or invokes readText synchronously — native paste takes priority (Chromium on Win/Linux synchronously dispatches paste during keydown default handling, handled by xterm handlePasteEvent as a single paste, no clipboard permission needed)
    • On keydown, nativePasteObserved is cleared; setTimeout(0) defers to a macrotask to check: if native paste occurred → skip readText (single paste); if not (macOS does not map this combo) → readText fallback
    • onNativePaste changes from interceptor to pure observer — no longer calls preventDefault / stopImmediatePropagation
    • Electron webview (readText rejected by permission) → native paste fires as single, no permission reject
  • 🟢 Also fixes Ctrl+Shift+V failing entirely in Electron webview: The v0.4.6 preventDefault() approach could not be undone when readText failed, causing webview to have no paste at all. The native-paste-first approach does not call preventDefault, so webview native paste fires normally as a single paste.

Verification

  • Type checking (pnpm run typecheck) and build (pnpm run build) both pass.
  • Tested Ctrl+Shift+V in local Chrome direct DSH + SSH to BJ-SF-Robot — pastes exactly once.
  • Tested Ctrl+Shift+V in dsh-remote-explorer via webview remote WSL — paste works (native paste fallback).
  • No configuration, API, or protocol changes — a page refresh applies the update.

Full Changelog: v0.4.6...v0.4.7

v0.4.6:修复 Ctrl+Shift+V 粘贴两次 / Fix Ctrl+Shift+V pasting text twice

Choose a tag to compare

@btsd321 btsd321 released this 28 Oct 09:38

中文

修复

  • 🟢 Ctrl+Shift+V 粘贴文本两次:xterm.js 的 _keyDown 在 customKeyHandler 返回 false 时直接 return false,不调用 ev.preventDefault()。Chromium 在 xterm 隐藏 textarea 上把 Ctrl+Shift+V 当作「粘贴为纯文本」,触发原生 paste 事件,被 xterm 内部的 handlePasteEvent 再发一次,与我们的 term.paste() 双发导致文本粘贴两次。SSH 到远程主机时更明显——远程 shell(bash/zsh)开启 bracketed paste mode,两次粘贴产生两段 \x1b[200~...\x1b[201~ 序列。现在 onCustomKey 在 readText 可用时调用 ev.preventDefault() 阻断浏览器原生 paste 事件;不安全上下文(远程 http 无 navigator.clipboard)不阻断,交给原生 paste 单发兜底。
  • 🟢 Ctrl+Shift+C 不安全上下文也能复制:原代码在无 navigator.clipboard.writeText 时不复制;现改为 writeClipboard()(内含 legacyCopy / execCommand 回落),并加 preventDefault() 阻断 Chrome 的 DevTools 审查元素快捷键。keydown 属用户手势,execCommand 在不安全上下文下可用。

验证

  • 类型检查(pnpm run typecheck)与构建(pnpm run build)均通过。
  • 在本地 Chrome、DSH 桌面端、远程 http 三种场景各按一次 Ctrl+Shift+V 确认只粘贴一次。
  • 无配置项、API 或协议变更,升级后刷新页面即生效。

English

Fixes

  • 🟢 Ctrl+Shift+V pasted text twice: xterm.js _keyDown returns false directly when customKeyHandler returns false, without calling ev.preventDefault(). Chromium treats Ctrl+Shift+V as "paste as plain text" on the xterm hidden textarea, firing a native paste event that xterm internal handlePasteEvent handles — sending the text a second time alongside our term.paste(). This was more noticeable over SSH, where remote shells (bash/zsh) enable bracketed paste mode, producing two \x1b[200~...\x1b[201~ sequences. onCustomKey now calls ev.preventDefault() when readText is available to suppress the native paste event; in insecure contexts (remote http without navigator.clipboard) it does not block, letting the native paste fire once as a fallback.
  • 🟢 Ctrl+Shift+C works in insecure contexts: Previously no copy happened without navigator.clipboard.writeText; now uses writeClipboard() (which falls back to legacyCopy / execCommand), and calls preventDefault() to block Chrome DevTools inspect-element shortcut. keydown is a user gesture, so execCommand works in insecure contexts.

Verification

  • Type checking (pnpm run typecheck) and build (pnpm run build) both pass.
  • Tested Ctrl+Shift+V in local Chrome, DSH desktop, and remote http — each pastes exactly once.
  • No configuration, API, or protocol changes — a page refresh applies the update.

Full Changelog: v0.4.5...v0.4.6

v0.4.5:终端面板与下拉菜单主题令牌成对配对,修复第三方皮肤下白底白字 / Theme-token pairing for the panel & dropdown, fixing white-on-white under third-party skins

Choose a tag to compare

@btsd321 btsd321 released this 23 Oct 23:27

中文

修复

  • 🟢 统一表面/文字令牌配对,修复下拉菜单与面板「白底白字」:此前面板与浮层底色取 --dsw-specific-tip(宿主设计平台的 tip 档、且当前宿主已无任何消费方的孤儿令牌,浅色主题下为近白 #F5F6F7),条目文字取 --dsw-alias-label-secondary。第三方皮肤可以经宿主公开的 theme.overrideTokens() 把该角色令牌整体改写并内联到 body(例如 dsh-plugin-wallpaper-engine 的字体集把「次要文字」设为 #FAFAFA),两枚令牌来源不同、失去成对关系,于是出现白底白字,只有鼠标悬停(文字切换为 primary)才可见。现在面板/栏/头部/侧栏/右侧列表改用宿主面板语义令牌,下拉菜单/右键菜单/输入框改用宿主浮层语义令牌;文字一律由 --dsw-alias-label-primary 派生(Text / TextDim / TextMuted 三档),边框与 hover 面同样收口。内部令牌声明在 :root,body 并带宿主令牌回退,浅色/深色、有无皮肤、独立模式与 DSH-better-sidebar 兼容模式表现一致。
  • 🟢 弱化文字同源收口:状态文字、图标、占位符与 focus 描边不再直接使用 --dsw-alias-label-tertiary(同样会被皮肤整体改写),改由主文字色派生的 --dshTermTextMuted 提供,避免浅色面板上对比度过低。

维护

  • 构建产物 lib/ 在主工作区重新构建,修正经 git worktree 构建时带入的相对路径前缀(不影响运行行为)。
  • 无配置项、API 或协议变更,升级后刷新页面即生效。

English

Fixes

  • 🟢 Pair surface and text theme tokens — fixes white-on-white in the dropdown and panel: The panel/menu background used --dsw-specific-tip (a tip-tier token with no consumer left in the host, near-white #F5F6F7 in the light theme) while item text used --dsw-alias-label-secondary. Third-party skins can rewrite that role token wholesale through the host's public theme.overrideTokens() and have it inlined on body (for example, a dsh-plugin-wallpaper-engine font set setting "secondary text" to #FAFAFA). The two tokens then come from unrelated sources and lose their pairing, producing white on white that only became visible on hover (when the text switches to primary). Panels/bars/header/side list now use the host's panel-surface semantic token, and the dropdown/context menu/inputs use the host's overlay-surface token; all text is derived from --dsw-alias-label-primary (Text / TextDim / TextMuted tiers), with borders and hover surfaces unified as well. The internal tokens are declared on :root,body with host-token fallbacks, so light/dark, with or without skins, and both standalone and DSH-better-sidebar compatibility modes behave the same.
  • 🟢 Derive muted text from the same source: state text, icons, placeholders and focus outlines no longer use --dsw-alias-label-tertiary directly (also rewritten wholesale by skins); they use --dshTermTextMuted, derived from the primary text color, avoiding low contrast on light panels.

Maintenance

  • Rebuilt the lib/ artifacts in the main workspace, correcting the relative path prefixes introduced by building inside a git worktree (no runtime impact).
  • No configuration, API or protocol changes — a page refresh applies the update.

Full Changelog: v0.4.4...v0.4.5

v0.4.4

Choose a tag to compare

@btsd321 btsd321 released this 17 Oct 21:24

Full Changelog: v0.4.3...v0.4.4

v0.4.3

Choose a tag to compare

@btsd321 btsd321 released this 09 Oct 22:13

Full Changelog: v0.4.2...v0.4.3

v0.4.2

Choose a tag to compare

@btsd321 btsd321 released this 08 Oct 19:41

Full Changelog: v0.4.1...v0.4.2

v0.4.1

Choose a tag to compare

@btsd321 btsd321 released this 03 Oct 19:51

Full Changelog: v0.4.0...v0.4.1

v0.4.0

Choose a tag to compare

@btsd321 btsd321 released this 02 Oct 19:01

Full Changelog: v0.3.0...v0.4.0

v0.3.0

Choose a tag to compare

@btsd321 btsd321 released this 30 Sep 06:47

Full Changelog: v0.2.8...v0.3.0

v0.2.8

Choose a tag to compare

@btsd321 btsd321 released this 30 Sep 05:29

Full Changelog: v0.2.7...v0.2.8