dsh-vscode-mode 0.1.21 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -20
- package/lib/client.js +711 -77
- package/lib/client.js.map +1 -1
- package/lib/index.js +113 -0
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
- package/src/client/events.ts +8 -4
- package/src/client/fileReveal.ts +28 -0
- package/src/client/index.ts +44 -9
- package/src/client/sidebar/contextMenu.ts +99 -0
- package/src/client/sidebar/menuItems.ts +28 -0
- package/src/client/sidebar/panels/FileExplorer.ts +34 -4
- package/src/client/sidebar/types.ts +5 -0
- package/src/client/sidebarBridge.ts +247 -0
- package/src/client/styles/editor.css +13 -1
- package/src/client/ui/ContextMenu.ts +82 -0
- package/src/client/ui/DiffBadge.ts +5 -3
- package/src/client/ui/EditorView.ts +113 -43
- package/src/client/ui/SideEditorTab.ts +48 -0
- package/src/compat.ts +2 -0
- package/src/reveal.ts +64 -0
- package/src/rpc.ts +21 -0
- package/src/shared/rpc.ts +2 -0
package/lib/client.js
CHANGED
|
@@ -29,7 +29,7 @@ window.__ModuleLoader__.load({
|
|
|
29
29
|
let react = require("react");
|
|
30
30
|
react = __toESM(react, 1);
|
|
31
31
|
//#region \0dsh-css:/home/runner/work/DSH_VsCodeMode/DSH_VsCodeMode/src/client/styles/editor.css.mjs
|
|
32
|
-
const css$1 = "/* dsh-vscode-mode 编辑区样式(原 ensureEdrvStyles 字符串,落盘为真 .css,由 tsdown CSS-inline 注入) */\n/* 浅色主题(对齐参考图:#f8f8f8 近白底 + 薄荷绿药丸 + 青绿文字 + 三文鱼 undo + 浅灰边框):\n 在 [data-edrv-view] 作用域内重定义 --dsw-alias-*,级联命中组件内联样式与 CSS。 */\n[data-edrv-view] { box-sizing: border-box; --edrv-tab-h: 34px; --dsw-alias-bg-base: #f8f8f8; --dsw-alias-bg-layer-1: #ffffff; --dsw-alias-bg-layer-2: #f0f4f4; --dsw-alias-bg-overlay: #ffffff; --dsw-alias-label-primary: #1f2933; --dsw-alias-label-secondary: #52606d; --dsw-alias-label-tertiary: #9aa5b1; --dsw-alias-border-l1: #e0e6e8; --dsw-alias-border-l2: #cbd2d9; --dsw-alias-brand-primary: #0f9d58; --dsw-alias-state-success-primary: #0f9d58; --dsw-alias-state-error-primary: #d9534f; --dsw-alias-state-warn-primary: #d97706; --dsw-alias-interactive-bg-hover: rgba(15,157,88,.08); }\n\n[data-edrv-view] .edrv-tabs { display: flex; align-items: center; gap: 2px; padding: 2px 8px 0; background: var(--dsw-alias-bg-layer-1, transparent); overflow-x: auto; scrollbar-width: thin; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 8px 0 12px; border: none; border-radius: 6px 6px 0 0; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 12px; cursor: pointer; white-space: nowrap; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-tab.edrv-tab-active { background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); box-shadow: inset 0 -2px 0 var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-tab .edrv-tab-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dsw-alias-brand-primary, #4f8cff); flex-shrink: 0; }\n[data-edrv-view] .edrv-tab .edrv-tab-x { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: 4px; color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; }\n[data-edrv-view] .edrv-tab .edrv-tab-x:hover { background: rgba(255,255,255,.12); color: var(--dsw-alias-label-primary, #eee); }\n[data-edrv-view] .edrv-tab-add { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; margin-left: 2px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 14px; cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab-add:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-pathbar { display: flex; align-items: center; gap: 8px; height: 26px; padding: 0 10px; background: var(--dsw-alias-bg-layer-1, #ffffff); border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); font-size: 12px; flex-shrink: 0; overflow: hidden; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-name { font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); white-space: nowrap; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-full { flex: 1; min-width: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; direction: rtl; text-align: left; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-meta { flex-shrink: 0; font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-variant-numeric: tabular-nums; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-status { color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-path-input { flex: 1; min-width: 140px; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search-wrap { position: relative; flex-shrink: 0; display: flex; align-items: center; padding: 2px 8px 2px 4px; }\n[data-edrv-view] .edrv-search { width: 190px; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search:focus { border-color: var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-search-pop { position: absolute; top: calc(100% + 4px); right: 8px; width: min(460px, calc(100vw - 24px)); max-height: 300px; overflow: auto; background: var(--dsw-alias-bg-overlay, #1c1c1c); border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 10px; box-shadow: 0 6px 20px rgba(0,0,0,.4); z-index: 60; padding: 4px; }\n[data-edrv-view] .edrv-search-item { display: flex; flex-direction: column; gap: 1px; padding: 5px 8px; border-radius: 6px; cursor: pointer; }\n[data-edrv-view] .edrv-search-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.07)); }\n[data-edrv-view] .edrv-search-item .n { color: var(--dsw-alias-label-primary, #eee); font-size: 12px; word-break: break-all; }\n[data-edrv-view] .edrv-search-item .d { color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-search-empty { padding: 8px; font-size: 12px; color: var(--dsw-alias-label-tertiary, #888); }\n[data-edrv-view] .edrv-btn-mini { font-size: 11px; padding: 2px 9px; border: none; border-radius: 999px; cursor: pointer; color: #fff; font-weight: 600; white-space: nowrap; }\n[data-edrv-view] .edrv-btn-keep { background: var(--dsw-alias-state-success-primary, #2e9e44); }\n[data-edrv-view] .edrv-btn-undo { background: var(--dsw-alias-state-warn-primary, #d97706); }\n[data-edrv-view] .edrv-btn-mini:disabled { opacity: .45; cursor: default; }\n[data-edrv-view] .edrv-statusbar { display: flex; align-items: center; gap: 10px; padding: 3px 10px; border-top: 1px solid var(--dsw-alias-border-l1, #333); background: var(--dsw-alias-bg-layer-1, transparent); font-size: 11px; color: var(--dsw-alias-label-tertiary, #888); flex-shrink: 0; white-space: nowrap; overflow: hidden; }\n[data-edrv-view] .edrv-statusbar .edrv-sp-path { flex: 1; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-diffchip { font-size: 11px; padding: 2px 10px; border: 1px solid var(--dsw-alias-border-l1, #333); border-radius: 999px; background: var(--dsw-alias-bg-layer-2, transparent); color: var(--dsw-alias-state-warn-primary, #b7791f); cursor: pointer; white-space: nowrap; flex-shrink: 0; }\n[data-edrv-view] .edrv-chip-btn { font-size: 12px; padding: 2px 6px; border: none; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); cursor: pointer; border-radius: 4px; flex-shrink: 0; }\n[data-edrv-view] .edrv-chip-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-mn-add-line { background: rgba(15,157,88,.10); }\n[data-edrv-view] .edrv-mn-gutter-add { color: #0f9d58 !important; font-weight: 700; display: flex !important; align-items: center; justify-content: center; }\n[data-edrv-view] .edrv-mn-gutter-add::before { content: \"+\"; }\n[data-edrv-view] .edrv-del-zone { background: #fdeaea; border-top: 1px solid rgba(217,83,79,.35); border-bottom: 1px solid rgba(217,83,79,.35); box-shadow: inset 0 0 0 1px rgba(217,83,79,.12); }\n[data-edrv-view] .edrv-del-row { white-space: pre; font-family: var(--ds-font-family-code, ui-monospace, monospace); font-size: 12.5px; line-height: 20px; color: #c0392b; }\n[data-edrv-view] .edrv-del-text { display: inline-block; white-space: pre; }\n[data-edrv-view] .edrv-minus-overlay { position: absolute; left: 0; top: 0; width: 100%; height: 100%; max-width: 100%; overflow: visible; pointer-events: none; z-index: 6; }\n[data-edrv-view] .edrv-minus-item { position: absolute; box-sizing: border-box; max-width: 100%; overflow: hidden; }\n[data-edrv-view] .edrv-minus-item::before { content: ''; position: absolute; left: 4px; top: 50%; width: 8px; height: 2px; transform: translateY(-50%); border-radius: 2px; background: #d9534f; }\n[data-edrv-view] .edrv-monaco-host { flex: 1 1 auto; min-width: 0; min-height: 0; position: relative; overflow: hidden; }\n[data-edrv-view] .edrv-monaco-host > div { position: absolute; inset: 0; min-width: 0; min-height: 0; }\n[data-edrv-view] .edrv-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; height: 100%; color: var(--dsw-alias-label-tertiary, #777); font-size: 13px; }\n[data-edrv-view] .edrv-diffbar { position: absolute; left: 0; right: 0; bottom: 10px; margin: 0 auto; z-index: 25; width: fit-content; max-width: calc(100% - 20px); border-radius: 12px; background: var(--dsw-specific-tip, var(--dsw-alias-bg-layer-2, #f0f4f4)); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); box-shadow: none; overflow: visible; display: flex; flex-direction: column; }\n[data-edrv-view] .edrv-editor-area > .edrv-diffbar { max-height: calc(100% - 20px); }\n[data-edrv-view] .edrv-diffbar-row { display: flex; align-items: center; gap: 6px; height: 36px; padding: 4px 5px 4px 12px; flex-wrap: nowrap; }\n[data-edrv-view] .edrv-diffbar-count { font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); min-width: 42px; text-align: center; white-space: nowrap; cursor: pointer; }\n[data-edrv-view] .edrv-diffbar-count.edrv-count-file { min-width: 64px; cursor: default; }\n[data-edrv-view] .edrv-diffbar-file { flex: 1; min-width: 0; font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-pill { font-size: 11px; padding: 3px 10px; border: none; border-radius: 999px; cursor: pointer; white-space: nowrap; font-weight: 600; }\n[data-edrv-view] .edrv-pill-keep { background: #e8f8e8; color: #0f7a45; border: 1px solid rgba(15,157,88,.4); }\n[data-edrv-view] .edrv-pill-undo { background: #fdeaea; color: #c0392b; border: 1px solid rgba(217,83,79,.4); }\n[data-edrv-view] .edrv-pill-ghost { background: #ffffff; color: var(--dsw-alias-label-secondary, #52606d); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-pill:disabled { opacity: .45; cursor: default; }\n[data-edrv-view] .edrv-diffbar-menu { position: absolute; right: 8px; bottom: calc(100% + 6px); z-index: 45; min-width: 160px; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 6px 20px rgba(31,41,51,.16); padding: 4px; display: flex; flex-direction: column; gap: 2px; }\n[data-edrv-view] .edrv-diffmenu-item { display: flex; align-items: center; gap: 8px; font-size: 12px; padding: 6px 10px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; text-align: left; }\n[data-edrv-view] .edrv-diffmenu-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-diffmenu-item.danger { color: var(--dsw-alias-state-error-primary, #d9534f); }\n[data-edrv-view] .edrv-diffmenu-sep { height: 1px; margin: 2px 4px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n/* 编辑区 / Tab 右键菜单(添加文件/选中内容到对话) */\n[data-edrv-view] .edrv-ctxmenu { position: fixed; z-index: 71; min-width: 200px; max-width: 320px; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 8px 26px rgba(31,41,51,.2); padding: 4px; display: flex; flex-direction: column; gap: 1px; }\n[data-edrv-view] .edrv-ctxmenu-item { display: flex; align-items: center; gap: 8px; font-size: 12px; line-height: 18px; padding: 7px 10px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-ctxmenu-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-ctxmenu-item.edrv-ctxmenu-danger { color: var(--dsw-alias-state-error-primary, #d9534f); }\n[data-edrv-view] .edrv-ctxmenu-sep { height: 1px; margin: 3px 4px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-diffbar-body { max-height: 130px; max-width: min(560px, calc(100vw - 40px)); overflow: auto; padding: 4px 8px 8px; display: flex; flex-direction: column; gap: 4px; border-top: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-diffrow { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); border-radius: 6px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); cursor: pointer; flex-wrap: wrap; }\n[data-edrv-view] .edrv-diffrow:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-diffrow-l { font-size: 11px; color: var(--dsw-alias-label-primary, #1f2933); min-width: 74px; font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-o { font-size: 11px; color: var(--dsw-alias-state-error-primary, #d9534f); font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-n { font-size: 11px; color: var(--dsw-alias-state-success-primary, #0f9d58); font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-tag { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-diffrow-stale { border-color: rgba(217,119,6,.5); cursor: default; }\n[data-edrv-view] .edrv-diffbox-others { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 4px 2px 0; border-top: 1px solid var(--dsw-alias-border-l1, #e0e6e8); margin-top: 2px; }\n[data-edrv-view] .edrv-diffrow-file { font-size: 11px; padding: 2px 10px; border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); border-radius: 999px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); color: var(--dsw-alias-label-secondary, #52606d); cursor: pointer; white-space: nowrap; max-width: 200px; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-diffrow-file:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); color: var(--dsw-alias-label-primary, #1f2933); }\n/* 编辑区 hover 差异块的 Keep/Undo 浮层 */\n[data-edrv-view] .edrv-hoveract { position: absolute; z-index: 30; display: flex; align-items: center; gap: 4px; padding: 2px 6px; border-radius: 8px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 4px 14px rgba(31,41,51,.14); }\n[data-edrv-view] .edrv-launch { position: absolute; left: 12px; right: 12px; bottom: 12px; z-index: 40; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #1c1c1c); border: 1px solid var(--dsw-alias-border-l2, #555); box-shadow: 0 6px 24px rgba(0,0,0,.5); display: flex; flex-direction: column; max-height: 60%; overflow: hidden; }\n[data-edrv-view] .edrv-launch-head { display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-bottom: 1px solid var(--dsw-alias-border-l1, #333); }\n[data-edrv-view] .edrv-launch-tab { font-size: 12px; padding: 3px 12px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); cursor: pointer; }\n[data-edrv-view] .edrv-launch-tab.on { background: var(--dsw-alias-bg-layer-2, transparent); color: var(--dsw-alias-label-primary, #eee); font-weight: 600; }\n[data-edrv-view] .edrv-launch-body { flex: 1; min-height: 0; overflow: auto; padding: 6px 8px; display: flex; flex-direction: column; gap: 4px; }\n[data-edrv-view] .edrv-launch-row { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1, #333); border-radius: 6px; cursor: pointer; flex-wrap: wrap; }\n[data-edrv-view] .edrv-launch-row:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-launch-path { flex: 1; min-width: 0; font-size: 12px; color: var(--dsw-alias-label-primary, #eee); word-break: break-all; }\n[data-edrv-view] .edrv-launch-cnt { font-size: 11px; color: var(--dsw-alias-label-tertiary, #888); white-space: nowrap; }\n[data-edrv-view] .edrv-launch-arch { display: flex; flex-direction: column; gap: 6px; }\n[data-edrv-view] .monaco-editor { overflow: hidden !important; }\n[data-edrv-view] .monaco-editor .sticky-widget { z-index: 30 !important; background: var(--dsw-alias-bg-base, #f8f8f8) !important; }\n[data-edrv-view] .monaco-editor .sticky-widget .sticky-line-content,\n[data-edrv-view] .monaco-editor .sticky-widget .sticky-line-number { background: var(--dsw-alias-bg-base, #f8f8f8) !important; }\n[data-edrv-view] .monaco-editor, [data-edrv-view] .monaco-editor .margin, [data-edrv-view] .monaco-editor-background { background: transparent !important; }\n[data-edrv-view] .monaco-editor .scrollbar .slider { background: rgba(128,128,128,.3) !important; }\n[data-edrv-view] .edrv-loading { gap: 8px; padding: 20px; }\n[data-edrv-view] .edrv-loading-title { color: var(--dsw-alias-label-primary, #1f2933); font-size: 13px; }\n[data-edrv-view] .edrv-progress { width: min(360px, 72%); height: 6px; overflow: hidden; border-radius: 999px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-progress-value { height: 100%; border-radius: inherit; background: var(--dsw-alias-brand-primary, #0f9d58); transition: width .24s ease; }\n[data-edrv-view] .edrv-loading-percent { color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; font-variant-numeric: tabular-nums; }\n@media (prefers-reduced-motion: reduce) {\n [data-edrv-view] .edrv-progress-value { transition: none; }\n}\n\n/* ===== 唯一会话级差异 dock(遵循 DSH todo/queue 原生布局) ===== */\n[data-edrv-diff-dock-shell] {\n box-sizing: border-box;\n width: calc(100% - var(--dsh-composer-side-clearance) - var(--dsh-composer-side-clearance) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset));\n max-width: calc(var(--dsh-composer-card-max-width) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset));\n margin: 0 auto;\n padding: 0;\n flex: none;\n border: 1px solid var(--dsw-alias-border-l1, #e0e6e8);\n border-radius: 12px;\n background: var(--dsw-specific-tip, var(--dsw-alias-bg-layer-2, transparent));\n box-shadow: none;\n overflow: hidden;\n}\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock {\n box-sizing: border-box;\n position: relative;\n left: auto;\n right: auto;\n bottom: auto;\n z-index: auto;\n width: 100%;\n max-width: none;\n margin: 0;\n display: flex;\n flex-direction: column;\n border: none;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n overflow: visible;\n}\n[data-edrv-diff-dock-shell] .edrv-diffbar-row { min-height: 36px; padding: 6px 12px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock-row { min-height: 36px; padding: 6px 12px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-body { max-height: 180px; overflow: auto; padding: 6px 12px 10px; border-top: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock-button { box-sizing: border-box; display: flex; align-items: center; justify-content: center; width: 100%; height: 24px; border: none; border-radius: 8px; padding: 0 12px; background: transparent; color: var(--dsw-alias-label-primary); font-size: 13px; font-weight: 500; line-height: 24px; text-align: center; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock-button:hover { background: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-diffbar-count { display: inline-flex; align-items: center; color: var(--dsw-alias-label-primary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 500; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-file { display: inline-flex; align-items: center; color: var(--dsw-alias-label-tertiary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 400; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-editor-row { display: flex; align-items: center; height: 36px; min-height: 36px; padding: 4px 12px; overflow-x: auto; scrollbar-width: thin; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-editor-content { display: flex; align-items: center; gap: 10px; width: 100%; min-width: max-content; min-height: 28px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-nav,\n[data-edrv-diff-dock-shell] .edrv-diffbar-files,\n[data-edrv-diff-dock-shell] .edrv-diffbar-actions { display: flex; align-items: center; gap: 6px; flex: none; height: 28px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-actions { margin-left: auto; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-details-toggle { display: inline-flex; align-items: center; justify-content: center; width: 28px; min-width: 28px; padding: 0; font-size: 13px; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-details-toggle svg { width: 14px; height: 14px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-files { min-width: 0; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-files .edrv-diffbar-file { min-width: 72px; max-width: 240px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-progress { min-width: 0; color: var(--dsw-alias-label-tertiary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 400; line-height: 24px; font-variant-numeric: tabular-nums; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-summary { min-width: 0; color: var(--dsw-alias-label-tertiary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 400; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-pill { box-sizing: border-box; height: 28px; padding: 0 9px; border: none; border-radius: 999px; cursor: pointer; white-space: nowrap; font-size: 11px; line-height: 26px; font-weight: 600; }\n[data-edrv-diff-dock-shell] .edrv-pill-keep { background: var(--dsw-alias-state-success-tertiary); color: var(--dsw-alias-state-success-primary); border: 1px solid var(--dsw-alias-state-success-secondary); }\n[data-edrv-diff-dock-shell] .edrv-pill-undo { background: var(--dsw-alias-state-error-tertiary); color: var(--dsw-alias-state-error-primary); border: 1px solid var(--dsw-alias-state-error-secondary); }\n[data-edrv-diff-dock-shell] .edrv-pill-ghost { background: transparent; color: var(--dsw-alias-label-secondary); border: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-pill:hover:not(:disabled) { background-color: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-pill:focus-visible { outline: 2px solid var(--dsw-alias-label-tertiary); outline-offset: -2px; }\n[data-edrv-diff-dock-shell] .edrv-pill:disabled { opacity: .45; cursor: default; }\n[data-edrv-diff-dock-shell] .edrv-diffrow { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; background: transparent; cursor: pointer; flex-wrap: wrap; }\n[data-edrv-diff-dock-shell] .edrv-diffrow:hover { background: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-l { color: var(--dsw-alias-label-primary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-o { color: var(--dsw-alias-state-error-primary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-n { color: var(--dsw-alias-state-success-primary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-tag { color: var(--dsw-alias-label-tertiary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-stale { border-color: var(--dsw-alias-state-warn-secondary); cursor: default; }\n[data-edrv-diff-dock-shell] .edrv-diffbox-others { border-top: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-file { border-color: var(--dsw-alias-border-l1); background: transparent; color: var(--dsw-alias-label-secondary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-file:hover { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-primary); }\n[data-edrv-diff-dock-shell] .edrv-diff-details { display: flex; flex-direction: column; gap: 2px; padding: 6px 12px 8px; border-top: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item { display: flex; align-items: center; width: 100%; min-height: 28px; gap: 8px; padding: 4px 8px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary); cursor: pointer; text-align: left; font-size: 12px; line-height: 20px; }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item.danger { color: var(--dsw-alias-state-error-primary); }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item:disabled { opacity: .45; cursor: default; }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-sep { height: 1px; margin: 2px 4px; background: var(--dsw-alias-border-l1); }\n@media (max-width: 620px) {\n [data-edrv-diff-dock-shell] .edrv-diffbar-editor-content { width: max-content; }\n [data-edrv-diff-dock-shell] .edrv-diffbar-files .edrv-diffbar-file { max-width: 160px; }\n}\n\n/* ===== 侧边栏(活动栏 + 面板区 + 文件树) ===== */\n[data-edrv-view] .edrv-editor-row { display: flex; flex: 1 1 auto; min-width: 0; min-height: 0; overflow: hidden; }\n[data-edrv-view] .edrv-main-col { box-sizing: border-box; min-width: 0; min-height: 0; overflow: hidden; }\n[data-edrv-view] .edrv-main-col > .edrv-pathbar,\n[data-edrv-view] .edrv-main-col > .edrv-tabs { flex: 0 0 auto; }\n[data-edrv-view] .edrv-editor-area { position: relative; display: flex; flex: 1 1 auto; flex-direction: column; min-width: 0; min-height: 0; overflow: hidden; }\n[data-edrv-view] .edrv-sidebar { display: flex; flex-direction: row; flex-shrink: 0; min-width: 0; height: 100%; background: var(--dsw-alias-bg-layer-1, #ffffff); border-right: 1px solid var(--dsw-alias-border-l1, #e0e6e8); overflow: hidden; }\n[data-edrv-view] .edrv-rail { display: flex; flex-direction: column; align-items: center; width: 44px; flex-shrink: 0; padding: 6px 0; background: var(--dsw-alias-bg-layer-2, #f0f4f4); border-right: 1px solid var(--dsw-alias-border-l1, #e0e6e8); gap: 4px; }\n[data-edrv-view] .edrv-rail-btn { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: none; border-radius: 8px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-rail-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-rail-btn.edrv-rail-on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.12)); color: var(--dsw-alias-label-primary, #1f2933); box-shadow: inset 2px 0 0 var(--dsw-alias-brand-primary, #0f9d58); }\n[data-edrv-view] .edrv-rail-icon { font-size: 15px; line-height: 1; }\n[data-edrv-view] .edrv-rail-badge { position: absolute; top: 2px; right: 2px; min-width: 14px; height: 14px; padding: 0 3px; border-radius: 999px; background: var(--dsw-alias-brand-primary, #0f9d58); color: #fff; font-size: 9px; font-weight: 600; line-height: 14px; text-align: center; box-sizing: border-box; }\n[data-edrv-view] .edrv-side-body { flex: 1; min-width: 0; min-height: 0; display: flex; overflow: hidden; }\n[data-edrv-view] .edrv-side-panel { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; }\n[data-edrv-view] .edrv-side-head { display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 10px 0 12px; border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); flex-shrink: 0; }\n[data-edrv-view] .edrv-side-title { font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); white-space: nowrap; }\n[data-edrv-view] .edrv-side-root { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-side-btn { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); font-size: 12px; cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-side-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-tree { flex: 1; min-height: 0; overflow: auto; padding: 4px 6px 12px; font-size: 12px; }\n[data-edrv-view] .edrv-tree-row { display: flex; align-items: center; gap: 4px; height: 22px; padding-right: 6px; border-radius: 5px; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; white-space: nowrap; }\n[data-edrv-view] .edrv-tree-row:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-tree-row.edrv-tree-active { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.14)); }\n[data-edrv-view] .edrv-tree-chev { width: 12px; flex-shrink: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 10px; text-align: center; }\n[data-edrv-view] .edrv-tree-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-tree-name.edrv-tree-dim { color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-tree-badge { min-width: 14px; height: 14px; padding: 0 4px; border-radius: 999px; background: var(--dsw-alias-state-warn-primary, #d97706); color: #fff; font-size: 9px; font-weight: 600; line-height: 14px; text-align: center; box-sizing: border-box; flex-shrink: 0; }\n[data-edrv-view] .edrv-tree-loading { height: 22px; line-height: 22px; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; }\n[data-edrv-view] .edrv-tree-error { display: flex; align-items: center; gap: 8px; margin: 4px 2px 6px; padding: 6px 8px; border: 1px solid rgba(217,83,79,.4); border-radius: 6px; background: #fdeaea; color: var(--dsw-alias-state-error-primary, #d9534f); font-size: 11px; }\n/* 大纲面板:kind 字形 / detail / 行号 */\n[data-edrv-view] .edrv-outline-kind { display: inline-flex; align-items: center; justify-content: center; width: 14px; flex-shrink: 0; font-size: 12px; font-weight: 600; text-align: center; }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-func { color: var(--dsw-alias-brand-primary, #0f9d58); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-type { color: var(--dsw-alias-label-primary, #1f2933); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-data { color: var(--dsw-alias-state-warn-primary, #d97706); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-ns { color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-key { color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-outline-detail { flex-shrink: 0; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; }\n[data-edrv-view] .edrv-outline-ln { flex-shrink: 0; padding-right: 2px; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 10px; font-variant-numeric: tabular-nums; }\n[data-edrv-view] .edrv-side-resize { width: 5px; flex-shrink: 0; cursor: col-resize; background: transparent; }\n[data-edrv-view] .edrv-side-resize:hover { background: var(--dsw-alias-brand-primary, #0f9d58); opacity: .35; }\n[data-edrv-view] .edrv-chip-btn.edrv-chip-on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.12)); color: var(--dsw-alias-label-primary, #1f2933); }\n\n";
|
|
32
|
+
const css$1 = "/* dsh-vscode-mode 编辑区样式(原 ensureEdrvStyles 字符串,落盘为真 .css,由 tsdown CSS-inline 注入) */\n/* 浅色主题(对齐参考图:#f8f8f8 近白底 + 薄荷绿药丸 + 青绿文字 + 三文鱼 undo + 浅灰边框):\n 在 [data-edrv-view] 作用域内重定义 --dsw-alias-*,级联命中组件内联样式与 CSS。 */\n[data-edrv-view] { box-sizing: border-box; --edrv-tab-h: 34px; --dsw-alias-bg-base: #f8f8f8; --dsw-alias-bg-layer-1: #ffffff; --dsw-alias-bg-layer-2: #f0f4f4; --dsw-alias-bg-overlay: #ffffff; --dsw-alias-label-primary: #1f2933; --dsw-alias-label-secondary: #52606d; --dsw-alias-label-tertiary: #9aa5b1; --dsw-alias-border-l1: #e0e6e8; --dsw-alias-border-l2: #cbd2d9; --dsw-alias-brand-primary: #0f9d58; --dsw-alias-state-success-primary: #0f9d58; --dsw-alias-state-error-primary: #d9534f; --dsw-alias-state-warn-primary: #d97706; --dsw-alias-interactive-bg-hover: rgba(15,157,88,.08); }\n\n[data-edrv-view] .edrv-tabs { display: flex; align-items: center; gap: 2px; padding: 2px 8px 0; background: var(--dsw-alias-bg-layer-1, transparent); overflow-x: auto; scrollbar-width: thin; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 8px 0 12px; border: none; border-radius: 6px 6px 0 0; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 12px; cursor: pointer; white-space: nowrap; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-tab.edrv-tab-active { background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); box-shadow: inset 0 -2px 0 var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-tab .edrv-tab-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dsw-alias-brand-primary, #4f8cff); flex-shrink: 0; }\n[data-edrv-view] .edrv-tab .edrv-tab-x { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: 4px; color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; }\n[data-edrv-view] .edrv-tab .edrv-tab-x:hover { background: rgba(255,255,255,.12); color: var(--dsw-alias-label-primary, #eee); }\n[data-edrv-view] .edrv-tab-add { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; margin-left: 2px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 14px; cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab-add:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-pathbar { display: flex; align-items: center; gap: 8px; height: 26px; padding: 0 10px; background: var(--dsw-alias-bg-layer-1, #ffffff); border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); font-size: 12px; flex-shrink: 0; overflow: hidden; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-name { font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); white-space: nowrap; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-full { flex: 1; min-width: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; direction: rtl; text-align: left; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-meta { flex-shrink: 0; font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-variant-numeric: tabular-nums; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-status { color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-path-input { flex: 1; min-width: 140px; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search-wrap { position: relative; flex-shrink: 0; display: flex; align-items: center; padding: 2px 8px 2px 4px; }\n[data-edrv-view] .edrv-search { width: 190px; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search:focus { border-color: var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-search-pop { position: absolute; top: calc(100% + 4px); right: 8px; width: min(460px, calc(100vw - 24px)); max-height: 300px; overflow: auto; background: var(--dsw-alias-bg-overlay, #1c1c1c); border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 10px; box-shadow: 0 6px 20px rgba(0,0,0,.4); z-index: 60; padding: 4px; }\n[data-edrv-view] .edrv-search-item { display: flex; flex-direction: column; gap: 1px; padding: 5px 8px; border-radius: 6px; cursor: pointer; }\n[data-edrv-view] .edrv-search-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.07)); }\n[data-edrv-view] .edrv-search-item .n { color: var(--dsw-alias-label-primary, #eee); font-size: 12px; word-break: break-all; }\n[data-edrv-view] .edrv-search-item .d { color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-search-empty { padding: 8px; font-size: 12px; color: var(--dsw-alias-label-tertiary, #888); }\n[data-edrv-view] .edrv-btn-mini { font-size: 11px; padding: 2px 9px; border: none; border-radius: 999px; cursor: pointer; color: #fff; font-weight: 600; white-space: nowrap; }\n[data-edrv-view] .edrv-btn-keep { background: var(--dsw-alias-state-success-primary, #2e9e44); }\n[data-edrv-view] .edrv-btn-undo { background: var(--dsw-alias-state-warn-primary, #d97706); }\n[data-edrv-view] .edrv-btn-mini:disabled { opacity: .45; cursor: default; }\n[data-edrv-view] .edrv-statusbar { display: flex; align-items: center; gap: 10px; padding: 3px 10px; border-top: 1px solid var(--dsw-alias-border-l1, #333); background: var(--dsw-alias-bg-layer-1, transparent); font-size: 11px; color: var(--dsw-alias-label-tertiary, #888); flex-shrink: 0; white-space: nowrap; overflow: hidden; }\n[data-edrv-view] .edrv-statusbar .edrv-sp-path { flex: 1; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-diffchip { font-size: 11px; padding: 2px 10px; border: 1px solid var(--dsw-alias-border-l1, #333); border-radius: 999px; background: var(--dsw-alias-bg-layer-2, transparent); color: var(--dsw-alias-state-warn-primary, #b7791f); cursor: pointer; white-space: nowrap; flex-shrink: 0; }\n[data-edrv-view] .edrv-chip-btn { font-size: 12px; padding: 2px 6px; border: none; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); cursor: pointer; border-radius: 4px; flex-shrink: 0; }\n[data-edrv-view] .edrv-chip-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-mn-add-line { background: rgba(15,157,88,.10); }\n[data-edrv-view] .edrv-mn-gutter-add { color: #0f9d58 !important; font-weight: 700; display: flex !important; align-items: center; justify-content: center; }\n[data-edrv-view] .edrv-mn-gutter-add::before { content: \"+\"; }\n[data-edrv-view] .edrv-del-zone { background: #fdeaea; border-top: 1px solid rgba(217,83,79,.35); border-bottom: 1px solid rgba(217,83,79,.35); box-shadow: inset 0 0 0 1px rgba(217,83,79,.12); }\n[data-edrv-view] .edrv-del-row { white-space: pre; font-family: var(--ds-font-family-code, ui-monospace, monospace); font-size: 12.5px; line-height: 20px; color: #c0392b; }\n[data-edrv-view] .edrv-del-text { display: inline-block; white-space: pre; }\n[data-edrv-view] .edrv-minus-overlay { position: absolute; left: 0; top: 0; width: 100%; height: 100%; max-width: 100%; overflow: visible; pointer-events: none; z-index: 6; }\n[data-edrv-view] .edrv-minus-item { position: absolute; box-sizing: border-box; max-width: 100%; overflow: hidden; }\n[data-edrv-view] .edrv-minus-item::before { content: ''; position: absolute; left: 4px; top: 50%; width: 8px; height: 2px; transform: translateY(-50%); border-radius: 2px; background: #d9534f; }\n[data-edrv-view] .edrv-monaco-host { flex: 1 1 auto; min-width: 0; min-height: 0; position: relative; overflow: hidden; }\n[data-edrv-view] .edrv-monaco-host > div { position: absolute; inset: 0; min-width: 0; min-height: 0; }\n[data-edrv-view] .edrv-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; height: 100%; color: var(--dsw-alias-label-tertiary, #777); font-size: 13px; }\n[data-edrv-view] .edrv-diffbar { position: absolute; left: 0; right: 0; bottom: 10px; margin: 0 auto; z-index: 25; width: fit-content; max-width: calc(100% - 20px); border-radius: 12px; background: var(--dsw-specific-tip, var(--dsw-alias-bg-layer-2, #f0f4f4)); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); box-shadow: none; overflow: visible; display: flex; flex-direction: column; }\n[data-edrv-view] .edrv-editor-area > .edrv-diffbar { max-height: calc(100% - 20px); }\n[data-edrv-view] .edrv-diffbar-row { display: flex; align-items: center; gap: 6px; height: 36px; padding: 4px 5px 4px 12px; flex-wrap: nowrap; }\n[data-edrv-view] .edrv-diffbar-count { font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); min-width: 42px; text-align: center; white-space: nowrap; cursor: pointer; }\n[data-edrv-view] .edrv-diffbar-count.edrv-count-file { min-width: 64px; cursor: default; }\n[data-edrv-view] .edrv-diffbar-file { flex: 1; min-width: 0; font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-pill { font-size: 11px; padding: 3px 10px; border: none; border-radius: 999px; cursor: pointer; white-space: nowrap; font-weight: 600; }\n[data-edrv-view] .edrv-pill-keep { background: #e8f8e8; color: #0f7a45; border: 1px solid rgba(15,157,88,.4); }\n[data-edrv-view] .edrv-pill-undo { background: #fdeaea; color: #c0392b; border: 1px solid rgba(217,83,79,.4); }\n[data-edrv-view] .edrv-pill-ghost { background: #ffffff; color: var(--dsw-alias-label-secondary, #52606d); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-pill:disabled { opacity: .45; cursor: default; }\n[data-edrv-view] .edrv-diffbar-menu { position: absolute; right: 8px; bottom: calc(100% + 6px); z-index: 45; min-width: 160px; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 6px 20px rgba(31,41,51,.16); padding: 4px; display: flex; flex-direction: column; gap: 2px; }\n[data-edrv-view] .edrv-diffmenu-item { display: flex; align-items: center; gap: 8px; font-size: 12px; padding: 6px 10px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; text-align: left; }\n[data-edrv-view] .edrv-diffmenu-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-diffmenu-item.danger { color: var(--dsw-alias-state-error-primary, #d9534f); }\n[data-edrv-view] .edrv-diffmenu-sep { height: 1px; margin: 2px 4px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n/* 编辑区 / Tab 右键菜单(添加文件/选中内容到对话) */\n[data-edrv-view] .edrv-ctxmenu { position: fixed; z-index: 71; min-width: 200px; max-width: 320px; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 8px 26px rgba(31,41,51,.2); padding: 4px; display: flex; flex-direction: column; gap: 1px; }\n[data-edrv-view] .edrv-ctxmenu-item { display: flex; align-items: center; gap: 8px; font-size: 12px; line-height: 18px; padding: 7px 10px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-ctxmenu-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-ctxmenu-item.edrv-ctxmenu-danger { color: var(--dsw-alias-state-error-primary, #d9534f); }\n[data-edrv-view] .edrv-ctxmenu-item:disabled,\n[data-edrv-view] .edrv-ctxmenu-item.edrv-ctxmenu-disabled { color: var(--dsw-alias-label-disabled, #b0b7c0); cursor: default; background: transparent; }\n[data-edrv-view] .edrv-ctxmenu-sep { height: 1px; margin: 3px 4px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-diffbar-body { max-height: 130px; max-width: min(560px, calc(100vw - 40px)); overflow: auto; padding: 4px 8px 8px; display: flex; flex-direction: column; gap: 4px; border-top: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-diffrow { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); border-radius: 6px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); cursor: pointer; flex-wrap: wrap; }\n[data-edrv-view] .edrv-diffrow:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-diffrow-l { font-size: 11px; color: var(--dsw-alias-label-primary, #1f2933); min-width: 74px; font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-o { font-size: 11px; color: var(--dsw-alias-state-error-primary, #d9534f); font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-n { font-size: 11px; color: var(--dsw-alias-state-success-primary, #0f9d58); font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-tag { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-diffrow-stale { border-color: rgba(217,119,6,.5); cursor: default; }\n[data-edrv-view] .edrv-diffbox-others { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 4px 2px 0; border-top: 1px solid var(--dsw-alias-border-l1, #e0e6e8); margin-top: 2px; }\n[data-edrv-view] .edrv-diffrow-file { font-size: 11px; padding: 2px 10px; border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); border-radius: 999px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); color: var(--dsw-alias-label-secondary, #52606d); cursor: pointer; white-space: nowrap; max-width: 200px; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-diffrow-file:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); color: var(--dsw-alias-label-primary, #1f2933); }\n/* 编辑区 hover 差异块的 Keep/Undo 浮层 */\n[data-edrv-view] .edrv-hoveract { position: absolute; z-index: 30; display: flex; align-items: center; gap: 4px; padding: 2px 6px; border-radius: 8px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 4px 14px rgba(31,41,51,.14); }\n[data-edrv-view] .edrv-launch { position: absolute; left: 12px; right: 12px; bottom: 12px; z-index: 40; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #1c1c1c); border: 1px solid var(--dsw-alias-border-l2, #555); box-shadow: 0 6px 24px rgba(0,0,0,.5); display: flex; flex-direction: column; max-height: 60%; overflow: hidden; }\n[data-edrv-view] .edrv-launch-head { display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-bottom: 1px solid var(--dsw-alias-border-l1, #333); }\n[data-edrv-view] .edrv-launch-tab { font-size: 12px; padding: 3px 12px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); cursor: pointer; }\n[data-edrv-view] .edrv-launch-tab.on { background: var(--dsw-alias-bg-layer-2, transparent); color: var(--dsw-alias-label-primary, #eee); font-weight: 600; }\n[data-edrv-view] .edrv-launch-body { flex: 1; min-height: 0; overflow: auto; padding: 6px 8px; display: flex; flex-direction: column; gap: 4px; }\n[data-edrv-view] .edrv-launch-row { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1, #333); border-radius: 6px; cursor: pointer; flex-wrap: wrap; }\n[data-edrv-view] .edrv-launch-row:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-launch-path { flex: 1; min-width: 0; font-size: 12px; color: var(--dsw-alias-label-primary, #eee); word-break: break-all; }\n[data-edrv-view] .edrv-launch-cnt { font-size: 11px; color: var(--dsw-alias-label-tertiary, #888); white-space: nowrap; }\n[data-edrv-view] .edrv-launch-arch { display: flex; flex-direction: column; gap: 6px; }\n[data-edrv-view] .monaco-editor { overflow: hidden !important; }\n[data-edrv-view] .monaco-editor .sticky-widget { z-index: 30 !important; background: var(--dsw-alias-bg-base, #f8f8f8) !important; }\n[data-edrv-view] .monaco-editor .sticky-widget .sticky-line-content,\n[data-edrv-view] .monaco-editor .sticky-widget .sticky-line-number { background: var(--dsw-alias-bg-base, #f8f8f8) !important; }\n[data-edrv-view] .monaco-editor, [data-edrv-view] .monaco-editor .margin, [data-edrv-view] .monaco-editor-background { background: transparent !important; }\n[data-edrv-view] .monaco-editor .scrollbar .slider { background: rgba(128,128,128,.3) !important; }\n[data-edrv-view] .edrv-loading { gap: 8px; padding: 20px; }\n[data-edrv-view] .edrv-loading-title { color: var(--dsw-alias-label-primary, #1f2933); font-size: 13px; }\n[data-edrv-view] .edrv-progress { width: min(360px, 72%); height: 6px; overflow: hidden; border-radius: 999px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-progress-value { height: 100%; border-radius: inherit; background: var(--dsw-alias-brand-primary, #0f9d58); transition: width .24s ease; }\n[data-edrv-view] .edrv-loading-percent { color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; font-variant-numeric: tabular-nums; }\n@media (prefers-reduced-motion: reduce) {\n [data-edrv-view] .edrv-progress-value { transition: none; }\n}\n\n/* ===== 唯一会话级差异 dock(遵循 DSH todo/queue 原生布局) ===== */\n[data-edrv-diff-dock-shell] {\n box-sizing: border-box;\n width: calc(100% - var(--dsh-composer-side-clearance) - var(--dsh-composer-side-clearance) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset));\n max-width: calc(var(--dsh-composer-card-max-width) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset));\n margin: 0 auto;\n padding: 0;\n flex: none;\n border: 1px solid var(--dsw-alias-border-l1, #e0e6e8);\n border-radius: 12px;\n background: var(--dsw-specific-tip, var(--dsw-alias-bg-layer-2, transparent));\n box-shadow: none;\n overflow: hidden;\n}\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock {\n box-sizing: border-box;\n position: relative;\n left: auto;\n right: auto;\n bottom: auto;\n z-index: auto;\n width: 100%;\n max-width: none;\n margin: 0;\n display: flex;\n flex-direction: column;\n border: none;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n overflow: visible;\n}\n[data-edrv-diff-dock-shell] .edrv-diffbar-row { min-height: 36px; padding: 6px 12px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock-row { min-height: 36px; padding: 6px 12px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-body { max-height: 180px; overflow: auto; padding: 6px 12px 10px; border-top: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock-button { box-sizing: border-box; display: flex; align-items: center; justify-content: center; width: 100%; height: 24px; border: none; border-radius: 8px; padding: 0 12px; background: transparent; color: var(--dsw-alias-label-primary); font-size: 13px; font-weight: 500; line-height: 24px; text-align: center; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-dock-button:hover { background: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-diffbar-count { display: inline-flex; align-items: center; color: var(--dsw-alias-label-primary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 500; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-file { display: inline-flex; align-items: center; color: var(--dsw-alias-label-tertiary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 400; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-editor-row { display: flex; align-items: center; height: 36px; min-height: 36px; padding: 4px 12px; overflow-x: auto; scrollbar-width: thin; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-editor-content { display: flex; align-items: center; gap: 10px; width: 100%; min-width: max-content; min-height: 28px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-nav,\n[data-edrv-diff-dock-shell] .edrv-diffbar-files,\n[data-edrv-diff-dock-shell] .edrv-diffbar-actions { display: flex; align-items: center; gap: 6px; flex: none; height: 28px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-actions { margin-left: auto; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-details-toggle { display: inline-flex; align-items: center; justify-content: center; width: 28px; min-width: 28px; padding: 0; font-size: 13px; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-details-toggle svg { width: 14px; height: 14px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-files { min-width: 0; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-files .edrv-diffbar-file { min-width: 72px; max-width: 240px; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-progress { min-width: 0; color: var(--dsw-alias-label-tertiary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 400; line-height: 24px; font-variant-numeric: tabular-nums; }\n[data-edrv-diff-dock-shell] .edrv-diffbar-summary { min-width: 0; color: var(--dsw-alias-label-tertiary); font-family: Inter, var(--dsw-font-family); font-size: 13px; font-weight: 400; line-height: 24px; }\n[data-edrv-diff-dock-shell] .edrv-pill { box-sizing: border-box; height: 28px; padding: 0 9px; border: none; border-radius: 999px; cursor: pointer; white-space: nowrap; font-size: 11px; line-height: 26px; font-weight: 600; }\n[data-edrv-diff-dock-shell] .edrv-pill-keep { background: var(--dsw-alias-state-success-tertiary); color: var(--dsw-alias-state-success-primary); border: 1px solid var(--dsw-alias-state-success-secondary); }\n[data-edrv-diff-dock-shell] .edrv-pill-undo { background: var(--dsw-alias-state-error-tertiary); color: var(--dsw-alias-state-error-primary); border: 1px solid var(--dsw-alias-state-error-secondary); }\n[data-edrv-diff-dock-shell] .edrv-pill-ghost { background: transparent; color: var(--dsw-alias-label-secondary); border: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-pill:hover:not(:disabled) { background-color: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-pill:focus-visible { outline: 2px solid var(--dsw-alias-label-tertiary); outline-offset: -2px; }\n[data-edrv-diff-dock-shell] .edrv-pill:disabled { opacity: .45; cursor: default; }\n[data-edrv-diff-dock-shell] .edrv-diffrow { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; background: transparent; cursor: pointer; flex-wrap: wrap; }\n[data-edrv-diff-dock-shell] .edrv-diffrow:hover { background: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-l { color: var(--dsw-alias-label-primary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-o { color: var(--dsw-alias-state-error-primary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-n { color: var(--dsw-alias-state-success-primary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-tag { color: var(--dsw-alias-label-tertiary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-stale { border-color: var(--dsw-alias-state-warn-secondary); cursor: default; }\n[data-edrv-diff-dock-shell] .edrv-diffbox-others { border-top: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-file { border-color: var(--dsw-alias-border-l1); background: transparent; color: var(--dsw-alias-label-secondary); }\n[data-edrv-diff-dock-shell] .edrv-diffrow-file:hover { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-primary); }\n[data-edrv-diff-dock-shell] .edrv-diff-details { display: flex; flex-direction: column; gap: 2px; padding: 6px 12px 8px; border-top: 1px solid var(--dsw-alias-border-l1); }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item { display: flex; align-items: center; width: 100%; min-height: 28px; gap: 8px; padding: 4px 8px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary); cursor: pointer; text-align: left; font-size: 12px; line-height: 20px; }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item.danger { color: var(--dsw-alias-state-error-primary); }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-item:disabled { opacity: .45; cursor: default; }\n[data-edrv-diff-dock-shell] .edrv-diff-details .edrv-diffmenu-sep { height: 1px; margin: 2px 4px; background: var(--dsw-alias-border-l1); }\n@media (max-width: 620px) {\n [data-edrv-diff-dock-shell] .edrv-diffbar-editor-content { width: max-content; }\n [data-edrv-diff-dock-shell] .edrv-diffbar-files .edrv-diffbar-file { max-width: 160px; }\n}\n\n/* ===== 侧边栏(活动栏 + 面板区 + 文件树) ===== */\n[data-edrv-view] .edrv-editor-row { display: flex; flex: 1 1 auto; min-width: 0; min-height: 0; overflow: hidden; }\n[data-edrv-view] .edrv-main-col { box-sizing: border-box; min-width: 0; min-height: 0; overflow: hidden; }\n[data-edrv-view] .edrv-main-col > .edrv-pathbar,\n[data-edrv-view] .edrv-main-col > .edrv-tabs { flex: 0 0 auto; }\n[data-edrv-view] .edrv-editor-area { position: relative; display: flex; flex: 1 1 auto; flex-direction: column; min-width: 0; min-height: 0; overflow: hidden; }\n[data-edrv-view] .edrv-sidebar { display: flex; flex-direction: row; flex-shrink: 0; min-width: 0; height: 100%; background: var(--dsw-alias-bg-layer-1, #ffffff); border-right: 1px solid var(--dsw-alias-border-l1, #e0e6e8); overflow: hidden; }\n[data-edrv-view] .edrv-rail { display: flex; flex-direction: column; align-items: center; width: 44px; flex-shrink: 0; padding: 6px 0; background: var(--dsw-alias-bg-layer-2, #f0f4f4); border-right: 1px solid var(--dsw-alias-border-l1, #e0e6e8); gap: 4px; }\n[data-edrv-view] .edrv-rail-btn { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: none; border-radius: 8px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-rail-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-rail-btn.edrv-rail-on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.12)); color: var(--dsw-alias-label-primary, #1f2933); box-shadow: inset 2px 0 0 var(--dsw-alias-brand-primary, #0f9d58); }\n[data-edrv-view] .edrv-rail-icon { font-size: 15px; line-height: 1; }\n[data-edrv-view] .edrv-rail-badge { position: absolute; top: 2px; right: 2px; min-width: 14px; height: 14px; padding: 0 3px; border-radius: 999px; background: var(--dsw-alias-brand-primary, #0f9d58); color: #fff; font-size: 9px; font-weight: 600; line-height: 14px; text-align: center; box-sizing: border-box; }\n[data-edrv-view] .edrv-side-body { flex: 1; min-width: 0; min-height: 0; display: flex; overflow: hidden; }\n[data-edrv-view] .edrv-side-panel { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; position: relative; }\n[data-edrv-view] .edrv-side-head { display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 10px 0 12px; border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); flex-shrink: 0; }\n[data-edrv-view] .edrv-side-title { font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); white-space: nowrap; }\n[data-edrv-view] .edrv-side-root { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-side-btn { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); font-size: 12px; cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-side-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-tree { flex: 1; min-height: 0; overflow: auto; padding: 4px 6px 12px; font-size: 12px; }\n[data-edrv-view] .edrv-tree-row { display: flex; align-items: center; gap: 4px; height: 22px; padding-right: 6px; border-radius: 5px; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; white-space: nowrap; }\n[data-edrv-view] .edrv-tree-row:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-tree-row.edrv-tree-active { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.14)); }\n[data-edrv-view] .edrv-tree-chev { width: 12px; flex-shrink: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 10px; text-align: center; }\n[data-edrv-view] .edrv-tree-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-tree-name.edrv-tree-dim { color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-tree-badge { min-width: 14px; height: 14px; padding: 0 4px; border-radius: 999px; background: var(--dsw-alias-state-warn-primary, #d97706); color: #fff; font-size: 9px; font-weight: 600; line-height: 14px; text-align: center; box-sizing: border-box; flex-shrink: 0; }\n[data-edrv-view] .edrv-tree-loading { height: 22px; line-height: 22px; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; }\n[data-edrv-view] .edrv-tree-error { display: flex; align-items: center; gap: 8px; margin: 4px 2px 6px; padding: 6px 8px; border: 1px solid rgba(217,83,79,.4); border-radius: 6px; background: #fdeaea; color: var(--dsw-alias-state-error-primary, #d9534f); font-size: 11px; }\n/* 大纲面板:kind 字形 / detail / 行号 */\n[data-edrv-view] .edrv-outline-kind { display: inline-flex; align-items: center; justify-content: center; width: 14px; flex-shrink: 0; font-size: 12px; font-weight: 600; text-align: center; }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-func { color: var(--dsw-alias-brand-primary, #0f9d58); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-type { color: var(--dsw-alias-label-primary, #1f2933); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-data { color: var(--dsw-alias-state-warn-primary, #d97706); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-ns { color: var(--dsw-alias-label-secondary, #52606d); }\n[data-edrv-view] .edrv-outline-kind.edrv-ol-key { color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-outline-detail { flex-shrink: 0; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; }\n[data-edrv-view] .edrv-outline-ln { flex-shrink: 0; padding-right: 2px; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 10px; font-variant-numeric: tabular-nums; }\n[data-edrv-view] .edrv-side-resize { width: 5px; flex-shrink: 0; cursor: col-resize; background: transparent; }\n[data-edrv-view] .edrv-side-resize:hover { background: var(--dsw-alias-brand-primary, #0f9d58); opacity: .35; }\n[data-edrv-view] .edrv-chip-btn.edrv-chip-on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.12)); color: var(--dsw-alias-label-primary, #1f2933); }\n\n/* ===== 侧栏形态(betterSidebar 面板内编辑区) ===== */\n[data-edrv-view][data-edrv-layout='side'] { box-sizing: border-box; height: 100%; }\n\n/* ===== 侧边栏引导条(旧页签形态、未装 betterSidebar 时) ===== */\n[data-edrv-view] .edrv-side-hint { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; flex-wrap: wrap; padding: 6px 12px; font-size: 12px; color: var(--dsw-alias-label-secondary, #52606d); background: var(--dsw-specific-tip, var(--dsw-alias-bg-layer-2, #f0f4f4)); border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-side-hint-text { white-space: nowrap; }\n[data-edrv-view] .edrv-side-hint-cmd { font-size: 11px; padding: 2px 6px; border-radius: 6px; background: var(--dsw-alias-bg-layer-1, #ffffff); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); color: var(--dsw-alias-label-primary, #1f2933); white-space: nowrap; }\n[data-edrv-view] .edrv-side-hint-close { margin-left: auto; border: none; background: transparent; color: var(--dsw-alias-label-tertiary, #9aa5b1); cursor: pointer; font-size: 14px; line-height: 1; padding: 2px 6px; border-radius: 6px; flex-shrink: 0; }\n[data-edrv-view] .edrv-side-hint-close:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); color: var(--dsw-alias-label-primary, #1f2933); }\n\n";
|
|
33
33
|
const tagId$1 = "dsh-vscode-mode/editor.css";
|
|
34
34
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
35
35
|
const tag = document.createElement("style");
|
|
@@ -75,14 +75,251 @@ window.__ModuleLoader__.load({
|
|
|
75
75
|
} catch (e) {}
|
|
76
76
|
}
|
|
77
77
|
//#endregion
|
|
78
|
+
//#region src/client/sidebarBridge.ts
|
|
79
|
+
/**
|
|
80
|
+
* dsh-vscode-mode client — 侧边栏编辑区桥:可选探测 dsh-better-sidebar 的
|
|
81
|
+
* ctx.betterSidebar 服务,并注册「文件编辑」Tab(单实例)。
|
|
82
|
+
* 可选依赖模式:服务缺失时调用方回退到中央页签形态;本模块不注册任何东西。
|
|
83
|
+
* 纯逻辑(探测/初始打开解析/角标计数)可单测,DOM/事件仅存在于 install 路径。
|
|
84
|
+
* 作者 ddj 2026年08月25号
|
|
85
|
+
*/
|
|
86
|
+
/** betterSidebar 服务名(ctx.get 用;不要加进 inject——缺失会让插件停靠等待)。 */
|
|
87
|
+
const BETTER_SIDEBAR_SERVICE = "betterSidebar";
|
|
88
|
+
/** 本插件在侧边栏注册的 Tab 类型 id(亦是 SidebarTab.type)。 */
|
|
89
|
+
const SIDE_TAB_ID = "edrv-editor";
|
|
90
|
+
/** 侧边栏 Tab 标题。 */
|
|
91
|
+
const SIDE_TAB_TITLE = "文件编辑";
|
|
92
|
+
/** 推荐安装命令(提示条/兼容性报告共用)。 */
|
|
93
|
+
const SIDEBAR_INSTALL_CMD = "dsh plugin --profile web add dsh-better-sidebar";
|
|
94
|
+
/**
|
|
95
|
+
* 解析 Tab 挂载时的初始打开请求(创建路径读 tab.path/meta,聚焦路径走窗口事件)。
|
|
96
|
+
* @author ddj 2026年08月25号
|
|
97
|
+
* @param tab 侧边栏 Tab(path/meta 为可选字段)
|
|
98
|
+
* @returns 待打开路径与是否聚焦差异
|
|
99
|
+
*/
|
|
100
|
+
function resolveInitialOpen(tab) {
|
|
101
|
+
const meta = tab?.meta ?? {};
|
|
102
|
+
return {
|
|
103
|
+
path: (typeof tab?.path === "string" && tab.path ? tab.path : typeof meta?.openPath === "string" ? meta.openPath : null) || null,
|
|
104
|
+
focusDiff: meta?.focusDiff === true
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/** 会话级待处理差异文件数缓存(Tab 角标同步读取;EditorView 侧栏形态写入)。 */
|
|
108
|
+
const sidePending = /* @__PURE__ */ new Map();
|
|
109
|
+
/**
|
|
110
|
+
* 写入会话的待处理差异文件数(0 视为清除,不显示角标)。
|
|
111
|
+
* @author ddj 2026年08月25号
|
|
112
|
+
* @param sessionId 会话 id
|
|
113
|
+
* @param count 待处理差异文件数
|
|
114
|
+
*/
|
|
115
|
+
function setSidePending(sessionId, count) {
|
|
116
|
+
if (!sessionId) return;
|
|
117
|
+
const value = Number.isFinite(count) ? Math.max(0, Math.floor(count)) : 0;
|
|
118
|
+
if (value > 0) sidePending.set(sessionId, value);
|
|
119
|
+
else sidePending.delete(sessionId);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* 读取会话的待处理差异文件数(角标用)。
|
|
123
|
+
* @author ddj 2026年08月25号
|
|
124
|
+
* @param sessionId 会话 id
|
|
125
|
+
* @returns 非负计数
|
|
126
|
+
*/
|
|
127
|
+
function getSidePending(sessionId) {
|
|
128
|
+
if (!sessionId) return 0;
|
|
129
|
+
return sidePending.get(sessionId) ?? 0;
|
|
130
|
+
}
|
|
131
|
+
/** 模块级侧栏打开路由(events.ts 优先走它;未注册 = 旧页签形态)。 */
|
|
132
|
+
let ensureSideEditor = null;
|
|
133
|
+
/** 待消费的初始打开(Tab 组件尚未挂载时暂存;按会话匹配,挂载时取走)。 */
|
|
134
|
+
let pendingOpen = null;
|
|
135
|
+
/** Tab 组件当前是否有挂载实例(有则直接投递窗口事件,无则暂存待消费)。 */
|
|
136
|
+
let sideEditorMounted = false;
|
|
137
|
+
/**
|
|
138
|
+
* 注册/撤销侧栏打开路由。
|
|
139
|
+
* @author ddj 2026年08月25号
|
|
140
|
+
* @param fn 路由函数或 null
|
|
141
|
+
*/
|
|
142
|
+
function setEnsureSideEditor(fn) {
|
|
143
|
+
ensureSideEditor = fn;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* 标记侧栏编辑器组件挂载状态(SideEditorTab 挂载/卸载时调用)。
|
|
147
|
+
* @author ddj 2026年08月25号
|
|
148
|
+
* @param mounted 是否已挂载
|
|
149
|
+
*/
|
|
150
|
+
function setSideEditorMounted(mounted) {
|
|
151
|
+
sideEditorMounted = mounted;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* 暂存指定会话的待消费初始打开(Tab 组件未挂载时由 install 路径调用)。
|
|
155
|
+
* @author ddj 2026年08月25号
|
|
156
|
+
* @param sessionId 会话 id
|
|
157
|
+
* @param path 待打开路径(可空)
|
|
158
|
+
* @param focusDiff 是否聚焦首个差异
|
|
159
|
+
*/
|
|
160
|
+
function stagePendingSideOpen(sessionId, path, focusDiff) {
|
|
161
|
+
if (!sessionId) return;
|
|
162
|
+
pendingOpen = {
|
|
163
|
+
sessionId,
|
|
164
|
+
path: path || null,
|
|
165
|
+
focusDiff: focusDiff === true
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* 取走指定会话的待消费初始打开(SideEditorTab 挂载时读取;不存在返回 null)。
|
|
170
|
+
* @author ddj 2026年08月25号
|
|
171
|
+
* @param sessionId 会话 id
|
|
172
|
+
* @returns 待打开请求或 null
|
|
173
|
+
*/
|
|
174
|
+
function takePendingSideOpen(sessionId) {
|
|
175
|
+
if (!pendingOpen || !sessionId || pendingOpen.sessionId !== sessionId) return null;
|
|
176
|
+
const value = {
|
|
177
|
+
path: pendingOpen.path,
|
|
178
|
+
focusDiff: pendingOpen.focusDiff
|
|
179
|
+
};
|
|
180
|
+
pendingOpen = null;
|
|
181
|
+
return value;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* 打开/聚焦侧栏编辑器(打开路径可选;返回是否已被侧栏形态接管)。
|
|
185
|
+
* @author ddj 2026年08月25号
|
|
186
|
+
* @param path 待打开路径(可空)
|
|
187
|
+
* @param focusDiff 是否聚焦首个差异
|
|
188
|
+
* @returns 是否路由成功
|
|
189
|
+
*/
|
|
190
|
+
function routeSideEditor(path, focusDiff) {
|
|
191
|
+
if (typeof ensureSideEditor !== "function") return false;
|
|
192
|
+
try {
|
|
193
|
+
return ensureSideEditor(path, focusDiff) === true;
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.warn("[dsh-vscode-mode] 侧栏编辑器打开失败(" + String(error) + "),已回退");
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* 结构化探测 betterSidebar 服务(可选依赖:缺失/降级返回 undefined)。
|
|
201
|
+
* @author ddj 2026年08月25号
|
|
202
|
+
* @param ctx 客户端服务上下文
|
|
203
|
+
* @returns 服务结构面或 undefined
|
|
204
|
+
*/
|
|
205
|
+
function detectSidebarService(ctx) {
|
|
206
|
+
try {
|
|
207
|
+
const service = ctx.get(BETTER_SIDEBAR_SERVICE);
|
|
208
|
+
if (!service || typeof service.registerTab !== "function" || typeof service.openTab !== "function") return void 0;
|
|
209
|
+
return service;
|
|
210
|
+
} catch {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* 注册侧边栏「文件编辑」Tab 并接管打开路由。
|
|
216
|
+
* Tab 被用户在 better-sidebar 设置里禁用时,打开路由降级为回退回调(中央页签)。
|
|
217
|
+
* @author ddj 2026年08月25号
|
|
218
|
+
* @param options 装配参数(组件依赖 + 活动会话解析 + 回退注册)
|
|
219
|
+
* @returns 卸载器(反注册 Tab + 撤销路由)
|
|
220
|
+
*/
|
|
221
|
+
function installSideEditor(options) {
|
|
222
|
+
const { service, renderTab, activeSession, registerLegacyFallback } = options;
|
|
223
|
+
let fallbackInstalled = false;
|
|
224
|
+
const open = (path, focusDiff) => {
|
|
225
|
+
if (typeof service.isTabEnabled === "function" && !service.isTabEnabled("edrv-editor")) {
|
|
226
|
+
if (!fallbackInstalled) {
|
|
227
|
+
fallbackInstalled = true;
|
|
228
|
+
try {
|
|
229
|
+
registerLegacyFallback();
|
|
230
|
+
} catch (error) {
|
|
231
|
+
console.warn("[dsh-vscode-mode] 回退注册失败(" + String(error) + ")");
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
const scope = activeSession();
|
|
237
|
+
const sessionId = scope?.sessionId;
|
|
238
|
+
if (!sessionId) return false;
|
|
239
|
+
try {
|
|
240
|
+
service.openTab({
|
|
241
|
+
type: SIDE_TAB_ID,
|
|
242
|
+
title: SIDE_TAB_TITLE,
|
|
243
|
+
...path ? { path } : {},
|
|
244
|
+
meta: {
|
|
245
|
+
openPath: path || void 0,
|
|
246
|
+
focusDiff
|
|
247
|
+
}
|
|
248
|
+
}, {
|
|
249
|
+
sessionId,
|
|
250
|
+
cwd: scope?.cwd
|
|
251
|
+
});
|
|
252
|
+
} catch (error) {
|
|
253
|
+
console.warn("[dsh-vscode-mode] openTab 失败(" + String(error) + ")");
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
if (sideEditorMounted) window.dispatchEvent(new CustomEvent("edrv:open-editor", { detail: {
|
|
257
|
+
path,
|
|
258
|
+
focusDiff
|
|
259
|
+
} }));
|
|
260
|
+
else stagePendingSideOpen(sessionId, path, focusDiff);
|
|
261
|
+
return true;
|
|
262
|
+
};
|
|
263
|
+
let tabDisposer = null;
|
|
264
|
+
try {
|
|
265
|
+
tabDisposer = service.registerTab({
|
|
266
|
+
id: SIDE_TAB_ID,
|
|
267
|
+
title: SIDE_TAB_TITLE,
|
|
268
|
+
icon: codeIcon,
|
|
269
|
+
single: true,
|
|
270
|
+
badge: (_ctx, scope) => getSidePending(scope?.sessionId) || null,
|
|
271
|
+
component: renderTab
|
|
272
|
+
});
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.warn("[dsh-vscode-mode] 侧边栏 Tab 注册失败(" + String(error) + ")");
|
|
275
|
+
if (!fallbackInstalled) {
|
|
276
|
+
fallbackInstalled = true;
|
|
277
|
+
try {
|
|
278
|
+
registerLegacyFallback();
|
|
279
|
+
} catch (inner) {
|
|
280
|
+
console.warn("[dsh-vscode-mode] 回退注册失败(" + String(inner) + ")");
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return () => {};
|
|
284
|
+
}
|
|
285
|
+
setEnsureSideEditor(open);
|
|
286
|
+
return () => {
|
|
287
|
+
if (typeof tabDisposer === "function") tabDisposer();
|
|
288
|
+
setEnsureSideEditor(null);
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* 侧边栏 Tab 图标(内联 SVG 代码括号,不依赖图标包)。
|
|
293
|
+
* @author ddj 2026年08月25号
|
|
294
|
+
* @param size 边长(px)
|
|
295
|
+
* @returns 图标元素
|
|
296
|
+
*/
|
|
297
|
+
function codeIcon(size) {
|
|
298
|
+
return react.default.createElement("svg", {
|
|
299
|
+
width: size,
|
|
300
|
+
height: size,
|
|
301
|
+
viewBox: "0 0 16 16",
|
|
302
|
+
fill: "none",
|
|
303
|
+
"aria-hidden": true,
|
|
304
|
+
focusable: false
|
|
305
|
+
}, react.default.createElement("path", {
|
|
306
|
+
d: "M5.5 4.5 2.5 8l3 3.5M10.5 4.5 13.5 8l-3 3.5",
|
|
307
|
+
stroke: "currentColor",
|
|
308
|
+
strokeWidth: 1.4,
|
|
309
|
+
strokeLinecap: "round",
|
|
310
|
+
strokeLinejoin: "round"
|
|
311
|
+
}));
|
|
312
|
+
}
|
|
313
|
+
//#endregion
|
|
78
314
|
//#region src/client/events.ts
|
|
79
315
|
/**
|
|
80
316
|
* dsh-vscode-mode client — 跨组件/跨 slot 的窗口事件助手。
|
|
81
|
-
* 迁移自原 src/client/index.ts 的 openEditorView
|
|
317
|
+
* 迁移自原 src/client/index.ts 的 openEditorView 与事件派发,语义不改;
|
|
318
|
+
* 侧边栏形态(sidebarBridge 已注册路由)优先,否则回退 DOM 页签点击。
|
|
82
319
|
* 作者 ddj 2026-08-20
|
|
83
320
|
*/
|
|
84
321
|
/**
|
|
85
|
-
* 选择中央「文件编辑」页签(DOM 级,无需 store actions
|
|
322
|
+
* 选择中央「文件编辑」页签(DOM 级,无需 store actions)。仅旧页签形态使用。
|
|
86
323
|
* @author ddj 2026年08月26号
|
|
87
324
|
*/
|
|
88
325
|
function selectEditorTab() {
|
|
@@ -93,11 +330,12 @@ window.__ModuleLoader__.load({
|
|
|
93
330
|
}
|
|
94
331
|
}
|
|
95
332
|
/**
|
|
96
|
-
*
|
|
333
|
+
* 打开「文件编辑」:侧边栏形态路由优先,旧形态回退中央页签。
|
|
97
334
|
* @author ddj 2026年08月26号
|
|
98
335
|
* @param path 要打开的路径(可空)
|
|
99
336
|
*/
|
|
100
337
|
function openEditorView(path) {
|
|
338
|
+
if (routeSideEditor(path ?? null, false)) return;
|
|
101
339
|
selectEditorTab();
|
|
102
340
|
const target = path ?? null;
|
|
103
341
|
setTimeout(() => {
|
|
@@ -105,11 +343,12 @@ window.__ModuleLoader__.load({
|
|
|
105
343
|
}, 80);
|
|
106
344
|
}
|
|
107
345
|
/**
|
|
108
|
-
*
|
|
346
|
+
* 打开文件编辑页并聚焦指定文件的首个差异(侧边栏形态自动展开面板)。
|
|
109
347
|
* @author ddj 2026年08月26号
|
|
110
348
|
* @param path 待聚焦的差异文件路径
|
|
111
349
|
*/
|
|
112
350
|
function openDiffView(path) {
|
|
351
|
+
if (routeSideEditor(path, true)) return;
|
|
113
352
|
selectEditorTab();
|
|
114
353
|
setTimeout(() => {
|
|
115
354
|
window.dispatchEvent(new CustomEvent("edrv:open-editor", { detail: {
|
|
@@ -1327,6 +1566,41 @@ window.__ModuleLoader__.load({
|
|
|
1327
1566
|
return Math.max(0, Math.min(scroll, Number.isFinite(composerTop) ? composerTop : scroll) - root);
|
|
1328
1567
|
}
|
|
1329
1568
|
//#endregion
|
|
1569
|
+
//#region src/client/fileReveal.ts
|
|
1570
|
+
/**
|
|
1571
|
+
* dsh-vscode-mode client — 「在文件浏览器中打开」RPC 包装(树菜单与 Monaco 右键共用)。
|
|
1572
|
+
* 归一化为 { ok, error? },不抛异常;无会话/异常降级返回错误文案。
|
|
1573
|
+
* 作者 ddj 2026-08-27
|
|
1574
|
+
*/
|
|
1575
|
+
/**
|
|
1576
|
+
* 请求 host 在 OS 文件浏览器中打开/定位路径。
|
|
1577
|
+
* @author ddj 2026年08月27号
|
|
1578
|
+
* @param sessionId 会话 id(可空)
|
|
1579
|
+
* @param path 工作区相对路径('' = 根目录)
|
|
1580
|
+
* @returns 成功或失败原因
|
|
1581
|
+
*/
|
|
1582
|
+
async function revealInExplorer(sessionId, path) {
|
|
1583
|
+
if (!sessionId) return {
|
|
1584
|
+
ok: false,
|
|
1585
|
+
error: "无活动会话"
|
|
1586
|
+
};
|
|
1587
|
+
try {
|
|
1588
|
+
const res = await rpc("edrv.revealInExplorer", {
|
|
1589
|
+
sessionId,
|
|
1590
|
+
path
|
|
1591
|
+
});
|
|
1592
|
+
return res.ok ? { ok: true } : {
|
|
1593
|
+
ok: false,
|
|
1594
|
+
error: res.error
|
|
1595
|
+
};
|
|
1596
|
+
} catch (error) {
|
|
1597
|
+
return {
|
|
1598
|
+
ok: false,
|
|
1599
|
+
error: "打开异常:" + String(error)
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
//#endregion
|
|
1330
1604
|
//#region src/client/ui/EditorView.ts
|
|
1331
1605
|
/**
|
|
1332
1606
|
* dsh-vscode-mode client — EditorView:中央 VSCode 式文件编辑器(编排层)。
|
|
@@ -1339,11 +1613,15 @@ window.__ModuleLoader__.load({
|
|
|
1339
1613
|
* 底部差异条(DiffBox/空态)+ 全局差异下拉(DiffLauncher)+ 状态栏。
|
|
1340
1614
|
* @param props.sessionId 会话 id
|
|
1341
1615
|
* @param props.schedule 延时调度(ctx.timeout)
|
|
1616
|
+
* @param props.layout 布局形态:'tab'(中央页签,默认)| 'side'(侧边栏面板)
|
|
1617
|
+
* @param props.sideHint 旧页签形态下显示侧边栏引导(安装命令)
|
|
1342
1618
|
*/
|
|
1343
1619
|
function EditorView(props) {
|
|
1344
1620
|
const sessionId = props?.sessionId;
|
|
1345
1621
|
const schedule = props.schedule;
|
|
1346
1622
|
const addToConversation = props.addToConversation;
|
|
1623
|
+
const layout = props?.layout === "side" ? "side" : "tab";
|
|
1624
|
+
const sideHint = props?.sideHint;
|
|
1347
1625
|
const [monaco, setMonaco] = react.default.useState(null);
|
|
1348
1626
|
const [monacoErr, setMonacoErr] = react.default.useState(null);
|
|
1349
1627
|
const [records, setRecords] = react.default.useState({});
|
|
@@ -1368,10 +1646,17 @@ window.__ModuleLoader__.load({
|
|
|
1368
1646
|
const [diffIdx, setDiffIdx] = react.default.useState(0);
|
|
1369
1647
|
const [fileIdx, setFileIdx] = react.default.useState(0);
|
|
1370
1648
|
const [tabMenu, setTabMenu] = react.default.useState(null);
|
|
1371
|
-
const [sidebarOn, setSidebarOn] = react.default.useState(
|
|
1649
|
+
const [sidebarOn, setSidebarOn] = react.default.useState(layout !== "side");
|
|
1372
1650
|
const [sidebarW, setSidebarW] = react.default.useState(240);
|
|
1373
1651
|
const [activePanel, setActivePanel] = react.default.useState("explorer");
|
|
1374
1652
|
const [focusRequest, setFocusRequest] = react.default.useState(0);
|
|
1653
|
+
const [hintDismissed, setHintDismissed] = react.default.useState(() => {
|
|
1654
|
+
try {
|
|
1655
|
+
return localStorage.getItem("edrv.side-hint-dismissed") === "1";
|
|
1656
|
+
} catch {
|
|
1657
|
+
return false;
|
|
1658
|
+
}
|
|
1659
|
+
});
|
|
1375
1660
|
const editorRef = react.default.useRef(null);
|
|
1376
1661
|
const viewRootRef = react.default.useRef(null);
|
|
1377
1662
|
const monacoRef = react.default.useRef(null);
|
|
@@ -1392,6 +1677,8 @@ window.__ModuleLoader__.load({
|
|
|
1392
1677
|
const batchBusyRef = react.default.useRef(false);
|
|
1393
1678
|
const menuHandlersRef = react.default.useRef(null);
|
|
1394
1679
|
const diffRendererRef = react.default.useRef(null);
|
|
1680
|
+
const layoutRef = react.default.useRef(layout);
|
|
1681
|
+
layoutRef.current = layout;
|
|
1395
1682
|
if (!diffRendererRef.current) diffRendererRef.current = createDiffRenderer((sid, t) => dbg(sid, t));
|
|
1396
1683
|
const currentRecords = react.default.useMemo(() => {
|
|
1397
1684
|
const list = [];
|
|
@@ -1521,8 +1808,12 @@ window.__ModuleLoader__.load({
|
|
|
1521
1808
|
};
|
|
1522
1809
|
}, [sessionId]);
|
|
1523
1810
|
const dockSourceRef = react.default.useRef({});
|
|
1524
|
-
react.default.useEffect(() => () =>
|
|
1811
|
+
react.default.useEffect(() => () => {
|
|
1812
|
+
clearDiffDock(sessionId, dockSourceRef.current);
|
|
1813
|
+
if (layout === "side") setSidePending(sessionId, 0);
|
|
1814
|
+
}, [sessionId]);
|
|
1525
1815
|
react.default.useLayoutEffect(() => {
|
|
1816
|
+
if (layout === "side") return;
|
|
1526
1817
|
const root = viewRootRef.current;
|
|
1527
1818
|
const scroll = root?.closest?.("[data-conversation-scroll]");
|
|
1528
1819
|
if (!root || !scroll) return;
|
|
@@ -1571,7 +1862,7 @@ window.__ModuleLoader__.load({
|
|
|
1571
1862
|
window.removeEventListener("resize", scheduleUpdate);
|
|
1572
1863
|
root.style.removeProperty("--edrv-editor-height");
|
|
1573
1864
|
};
|
|
1574
|
-
}, [sessionId]);
|
|
1865
|
+
}, [sessionId, layout]);
|
|
1575
1866
|
react.default.useEffect(() => {
|
|
1576
1867
|
if (bootRef.current || !sessionId) return;
|
|
1577
1868
|
bootRef.current = true;
|
|
@@ -1599,10 +1890,11 @@ window.__ModuleLoader__.load({
|
|
|
1599
1890
|
active,
|
|
1600
1891
|
sessionId
|
|
1601
1892
|
]);
|
|
1893
|
+
const sidebarKey = "edrv.sidebar." + (layout === "side" ? "side." : "") + String(sessionId);
|
|
1602
1894
|
react.default.useEffect(() => {
|
|
1603
1895
|
if (!sessionId) return;
|
|
1604
1896
|
try {
|
|
1605
|
-
const raw = localStorage.getItem(
|
|
1897
|
+
const raw = localStorage.getItem(sidebarKey);
|
|
1606
1898
|
if (raw) {
|
|
1607
1899
|
const saved = JSON.parse(raw);
|
|
1608
1900
|
if (typeof saved.on === "boolean") setSidebarOn(saved.on);
|
|
@@ -1610,11 +1902,11 @@ window.__ModuleLoader__.load({
|
|
|
1610
1902
|
if (typeof saved.panel === "string") setActivePanel(saved.panel);
|
|
1611
1903
|
}
|
|
1612
1904
|
} catch (e) {}
|
|
1613
|
-
}, [sessionId]);
|
|
1905
|
+
}, [sessionId, sidebarKey]);
|
|
1614
1906
|
react.default.useEffect(() => {
|
|
1615
1907
|
if (!sessionId) return;
|
|
1616
1908
|
try {
|
|
1617
|
-
localStorage.setItem(
|
|
1909
|
+
localStorage.setItem(sidebarKey, JSON.stringify({
|
|
1618
1910
|
on: sidebarOn,
|
|
1619
1911
|
width: sidebarW,
|
|
1620
1912
|
panel: activePanel
|
|
@@ -1624,7 +1916,8 @@ window.__ModuleLoader__.load({
|
|
|
1624
1916
|
sidebarOn,
|
|
1625
1917
|
sidebarW,
|
|
1626
1918
|
activePanel,
|
|
1627
|
-
sessionId
|
|
1919
|
+
sessionId,
|
|
1920
|
+
sidebarKey
|
|
1628
1921
|
]);
|
|
1629
1922
|
react.default.useEffect(() => {
|
|
1630
1923
|
const onKey = (e) => {
|
|
@@ -1790,6 +2083,7 @@ window.__ModuleLoader__.load({
|
|
|
1790
2083
|
}
|
|
1791
2084
|
if (editorRef.current || !monacoRef.current) return;
|
|
1792
2085
|
const m = monacoRef.current;
|
|
2086
|
+
const side = layoutRef.current === "side";
|
|
1793
2087
|
const ed = m.editor.create(node, {
|
|
1794
2088
|
value: "",
|
|
1795
2089
|
language: "plaintext",
|
|
@@ -1798,7 +2092,7 @@ window.__ModuleLoader__.load({
|
|
|
1798
2092
|
fontSize: 13,
|
|
1799
2093
|
lineHeight: 20,
|
|
1800
2094
|
minimap: {
|
|
1801
|
-
enabled:
|
|
2095
|
+
enabled: !side,
|
|
1802
2096
|
scale: 1
|
|
1803
2097
|
},
|
|
1804
2098
|
glyphMargin: true,
|
|
@@ -1810,7 +2104,7 @@ window.__ModuleLoader__.load({
|
|
|
1810
2104
|
renderWhitespace: "selection",
|
|
1811
2105
|
smoothScrolling: true,
|
|
1812
2106
|
cursorBlinking: "smooth",
|
|
1813
|
-
padding: { top: 8 }
|
|
2107
|
+
padding: { top: side ? 6 : 8 }
|
|
1814
2108
|
});
|
|
1815
2109
|
ed.addCommand(m.KeyMod.CtrlCmd | m.KeyCode.KeyS, () => {
|
|
1816
2110
|
flushSave();
|
|
@@ -1863,6 +2157,13 @@ window.__ModuleLoader__.load({
|
|
|
1863
2157
|
});
|
|
1864
2158
|
}
|
|
1865
2159
|
});
|
|
2160
|
+
ed.addAction({
|
|
2161
|
+
id: "edrv.revealInExplorer",
|
|
2162
|
+
label: "在文件浏览器中打开",
|
|
2163
|
+
contextMenuGroupId: "1_edrv",
|
|
2164
|
+
precondition: "editorTextFocus",
|
|
2165
|
+
run: (edx) => menuHandlers()?.openInExplorer(pathOf(edx))
|
|
2166
|
+
});
|
|
1866
2167
|
const hideSoon = () => {
|
|
1867
2168
|
if (hoverEditorRef.current || hoverPanelRef.current || hideTimerRef.current) return;
|
|
1868
2169
|
hideTimerRef.current = setTimeout(() => {
|
|
@@ -2167,7 +2468,30 @@ window.__ModuleLoader__.load({
|
|
|
2167
2468
|
}
|
|
2168
2469
|
addToConversation.appendReference(sessionId, path, range).then((o) => setStatus(statusOfAdd(o, "已添加文件引用")));
|
|
2169
2470
|
};
|
|
2170
|
-
|
|
2471
|
+
/**
|
|
2472
|
+
* 在 OS 文件浏览器中打开/定位路径(Monaco 右键菜单用,状态栏反馈)。
|
|
2473
|
+
* @author ddj 2026年08月27号
|
|
2474
|
+
* @param path 工作区相对路径(可能为 null)
|
|
2475
|
+
*/
|
|
2476
|
+
const openInExplorer = (path) => {
|
|
2477
|
+
if (!path) {
|
|
2478
|
+
setStatus("无活动文件");
|
|
2479
|
+
return;
|
|
2480
|
+
}
|
|
2481
|
+
if (!sessionId) {
|
|
2482
|
+
setStatus("无活动会话");
|
|
2483
|
+
return;
|
|
2484
|
+
}
|
|
2485
|
+
setStatus("正在打开文件浏览器…");
|
|
2486
|
+
revealInExplorer(sessionId, path).then((outcome) => {
|
|
2487
|
+
setStatus(outcome.ok ? "已在文件浏览器中打开" : "打开失败");
|
|
2488
|
+
if (!outcome.ok && outcome.error) setError(outcome.error);
|
|
2489
|
+
});
|
|
2490
|
+
};
|
|
2491
|
+
menuHandlersRef.current = {
|
|
2492
|
+
addRefToChat,
|
|
2493
|
+
openInExplorer
|
|
2494
|
+
};
|
|
2171
2495
|
const openFile = (path, focusDiff) => {
|
|
2172
2496
|
if (!path) return;
|
|
2173
2497
|
addTab(path, true);
|
|
@@ -2369,39 +2693,42 @@ window.__ModuleLoader__.load({
|
|
|
2369
2693
|
actHunk(hoverAct.region, true);
|
|
2370
2694
|
}
|
|
2371
2695
|
}, "↩ Undo")) : null;
|
|
2696
|
+
/** 组装差异 dock 快照(发布给 conversation.input.dock 的唯一 DiffBox 实例)。 */
|
|
2697
|
+
const buildDockSnapshot = () => ({
|
|
2698
|
+
mode: editorDockMode(active),
|
|
2699
|
+
pendingRegions,
|
|
2700
|
+
staleRegions,
|
|
2701
|
+
onAct: actHunk,
|
|
2702
|
+
onAcceptFile: acceptFile,
|
|
2703
|
+
onUndoFile: undoFile,
|
|
2704
|
+
onAcceptAllFiles: acceptAllFiles,
|
|
2705
|
+
onUndoAllFiles: undoAllFiles,
|
|
2706
|
+
allPendingCount: allPending.length,
|
|
2707
|
+
onRollback: rollbackFile,
|
|
2708
|
+
onJump: jumpTo,
|
|
2709
|
+
otherFiles,
|
|
2710
|
+
onOpenOther: (path) => openFile(path, true),
|
|
2711
|
+
onOpenLauncher: (tab) => {
|
|
2712
|
+
setLauncherTab(tab || "pending");
|
|
2713
|
+
setLauncherOpen(true);
|
|
2714
|
+
},
|
|
2715
|
+
onRefresh: reloadFile,
|
|
2716
|
+
activePath: active,
|
|
2717
|
+
diffIdx: contentReady ? diffIdx : 0,
|
|
2718
|
+
diffTotal: displayDiffTotal(contentReady, pendingRegions.length, sum.files.find((file) => file.path === active)?.pending ?? 0),
|
|
2719
|
+
fileIdx,
|
|
2720
|
+
fileTotal: sum.pendingFiles.length,
|
|
2721
|
+
onPrevDiff: () => gotoDiff(-1),
|
|
2722
|
+
onNextDiff: () => gotoDiff(1),
|
|
2723
|
+
onPrevFile: () => gotoFile(-1),
|
|
2724
|
+
onNextFile: () => gotoFile(1),
|
|
2725
|
+
onOpenNextFile: openNextFile
|
|
2726
|
+
});
|
|
2372
2727
|
react.default.useEffect(() => {
|
|
2373
2728
|
if (!sessionId) return;
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
pendingRegions,
|
|
2378
|
-
staleRegions,
|
|
2379
|
-
onAct: actHunk,
|
|
2380
|
-
onAcceptFile: acceptFile,
|
|
2381
|
-
onUndoFile: undoFile,
|
|
2382
|
-
onAcceptAllFiles: acceptAllFiles,
|
|
2383
|
-
onUndoAllFiles: undoAllFiles,
|
|
2384
|
-
allPendingCount: allPending.length,
|
|
2385
|
-
onRollback: rollbackFile,
|
|
2386
|
-
onJump: jumpTo,
|
|
2387
|
-
otherFiles,
|
|
2388
|
-
onOpenOther: (path) => openFile(path, true),
|
|
2389
|
-
onOpenLauncher: (tab) => {
|
|
2390
|
-
setLauncherTab(tab || "pending");
|
|
2391
|
-
setLauncherOpen(true);
|
|
2392
|
-
},
|
|
2393
|
-
onRefresh: reloadFile,
|
|
2394
|
-
activePath: active,
|
|
2395
|
-
diffIdx: contentReady ? diffIdx : 0,
|
|
2396
|
-
diffTotal: displayDiffTotal(contentReady, pendingRegions.length, sum.files.find((file) => file.path === active)?.pending ?? 0),
|
|
2397
|
-
fileIdx,
|
|
2398
|
-
fileTotal: sum.pendingFiles.length,
|
|
2399
|
-
onPrevDiff: () => gotoDiff(-1),
|
|
2400
|
-
onNextDiff: () => gotoDiff(1),
|
|
2401
|
-
onPrevFile: () => gotoFile(-1),
|
|
2402
|
-
onNextFile: () => gotoFile(1),
|
|
2403
|
-
onOpenNextFile: openNextFile
|
|
2404
|
-
}, dockSourceRef.current);
|
|
2729
|
+
publishDiffDock(sessionId, buildDockSnapshot(), dockSourceRef.current);
|
|
2730
|
+
if (layout === "side") setSidePending(sessionId, sum.totalFiles);
|
|
2731
|
+
else setSidePending(sessionId, 0);
|
|
2405
2732
|
});
|
|
2406
2733
|
const overlay = launcherOpen ? react.default.createElement(react.default.Fragment, null, react.default.createElement("div", {
|
|
2407
2734
|
style: {
|
|
@@ -2468,9 +2795,30 @@ window.__ModuleLoader__.load({
|
|
|
2468
2795
|
},
|
|
2469
2796
|
refreshRecords: () => refreshRecords(),
|
|
2470
2797
|
editor: () => editorRef.current,
|
|
2471
|
-
outlineSources: props.outlineSources
|
|
2798
|
+
outlineSources: props.outlineSources,
|
|
2799
|
+
fileMenuItems: props.fileMenuItems,
|
|
2800
|
+
notify: (message) => setStatus(message)
|
|
2472
2801
|
};
|
|
2473
2802
|
const editorArea = react.default.createElement("div", { className: "edrv-editor-area" }, body, hoverEl, overlay);
|
|
2803
|
+
const dismissHint = () => {
|
|
2804
|
+
setHintDismissed(true);
|
|
2805
|
+
try {
|
|
2806
|
+
localStorage.setItem("edrv.side-hint-dismissed", "1");
|
|
2807
|
+
} catch (e) {}
|
|
2808
|
+
};
|
|
2809
|
+
const copyInstallCmd = () => {
|
|
2810
|
+
if (navigator.clipboard?.writeText) navigator.clipboard.writeText(SIDEBAR_INSTALL_CMD).catch(() => {});
|
|
2811
|
+
};
|
|
2812
|
+
const sideHintEl = layout === "tab" && sideHint && !hintDismissed ? react.default.createElement("div", { className: "edrv-side-hint" }, react.default.createElement("span", { className: "edrv-side-hint-text" }, "安装 dsh-better-sidebar 后可启用侧边栏编辑(对话+编辑同屏):"), react.default.createElement("code", { className: "edrv-side-hint-cmd" }, SIDEBAR_INSTALL_CMD), react.default.createElement("button", {
|
|
2813
|
+
className: "edrv-pill edrv-pill-ghost",
|
|
2814
|
+
title: "复制安装命令",
|
|
2815
|
+
onClick: copyInstallCmd
|
|
2816
|
+
}, "复制命令"), react.default.createElement("button", {
|
|
2817
|
+
className: "edrv-side-hint-close",
|
|
2818
|
+
title: "关闭提示",
|
|
2819
|
+
"aria-label": "关闭提示",
|
|
2820
|
+
onClick: dismissHint
|
|
2821
|
+
}, "×")) : null;
|
|
2474
2822
|
const mainCol = react.default.createElement("div", {
|
|
2475
2823
|
className: "edrv-main-col",
|
|
2476
2824
|
style: {
|
|
@@ -2481,7 +2829,7 @@ window.__ModuleLoader__.load({
|
|
|
2481
2829
|
flexDirection: "column",
|
|
2482
2830
|
overflow: "hidden"
|
|
2483
2831
|
}
|
|
2484
|
-
}, pathBar, tabRow, editorArea);
|
|
2832
|
+
}, pathBar, tabRow, sideHintEl, editorArea);
|
|
2485
2833
|
const editorRow = react.default.createElement("div", { className: "edrv-editor-row" }, sidebarOn && sidebarPanels ? react.default.createElement(SidebarView, {
|
|
2486
2834
|
registry: sidebarPanels,
|
|
2487
2835
|
ctx: sidebarCtx,
|
|
@@ -2491,18 +2839,26 @@ window.__ModuleLoader__.load({
|
|
|
2491
2839
|
onWidth: setSidebarW,
|
|
2492
2840
|
onHide: () => setSidebarOn(false)
|
|
2493
2841
|
}) : null, mainCol);
|
|
2494
|
-
|
|
2842
|
+
const baseStyle = {
|
|
2843
|
+
minHeight: 0,
|
|
2844
|
+
display: "flex",
|
|
2845
|
+
flexDirection: "column",
|
|
2846
|
+
background: "var(--dsw-alias-bg-base,transparent)",
|
|
2847
|
+
overflow: "hidden"
|
|
2848
|
+
};
|
|
2849
|
+
return layout === "side" ? react.default.createElement("div", {
|
|
2495
2850
|
ref: viewRootRef,
|
|
2496
2851
|
"data-edrv-view": "1",
|
|
2497
|
-
|
|
2852
|
+
"data-edrv-layout": "side",
|
|
2853
|
+
className: "edrv-view-side",
|
|
2854
|
+
style: Object.assign({}, baseStyle, { height: "100%" })
|
|
2855
|
+
}, editorRow, menuBackdrop, tabMenuEl) : react.default.createElement("div", {
|
|
2856
|
+
ref: viewRootRef,
|
|
2857
|
+
"data-edrv-view": "1",
|
|
2858
|
+
style: Object.assign({}, baseStyle, {
|
|
2498
2859
|
height: "var(--edrv-editor-height, 100%)",
|
|
2499
|
-
maxHeight: "var(--edrv-editor-height, 100%)"
|
|
2500
|
-
|
|
2501
|
-
display: "flex",
|
|
2502
|
-
flexDirection: "column",
|
|
2503
|
-
background: "var(--dsw-alias-bg-base,transparent)",
|
|
2504
|
-
overflow: "hidden"
|
|
2505
|
-
}
|
|
2860
|
+
maxHeight: "var(--edrv-editor-height, 100%)"
|
|
2861
|
+
})
|
|
2506
2862
|
}, editorRow, menuBackdrop, tabMenuEl);
|
|
2507
2863
|
}
|
|
2508
2864
|
//#endregion
|
|
@@ -2517,14 +2873,14 @@ window.__ModuleLoader__.load({
|
|
|
2517
2873
|
*/
|
|
2518
2874
|
function DiffBadge(props) {
|
|
2519
2875
|
const sessionId = props?.sessionId;
|
|
2520
|
-
const [
|
|
2876
|
+
const [summary, setSummary] = react.default.useState(null);
|
|
2521
2877
|
const seq = react.default.useRef(0);
|
|
2522
2878
|
const load = react.default.useCallback(() => {
|
|
2523
2879
|
if (!sessionId) return;
|
|
2524
2880
|
const s = ++seq.current;
|
|
2525
2881
|
rpc("edrv.list", { sessionId }).then((res) => {
|
|
2526
2882
|
if (s !== seq.current || !res || !res.ok || !Array.isArray(res.records)) return;
|
|
2527
|
-
|
|
2883
|
+
setSummary(summarize(res.records));
|
|
2528
2884
|
}).catch(() => {});
|
|
2529
2885
|
}, [sessionId]);
|
|
2530
2886
|
react.default.useEffect(() => {
|
|
@@ -2537,9 +2893,10 @@ window.__ModuleLoader__.load({
|
|
|
2537
2893
|
window.removeEventListener("edrv:refresh", onRefresh);
|
|
2538
2894
|
};
|
|
2539
2895
|
}, [load]);
|
|
2896
|
+
const n = summary?.totalFiles ?? 0;
|
|
2540
2897
|
if (!n) return null;
|
|
2541
2898
|
const click = () => {
|
|
2542
|
-
openEditorView(null);
|
|
2899
|
+
openEditorView(summary?.pendingFiles?.[0]?.path ?? null);
|
|
2543
2900
|
setTimeout(() => {
|
|
2544
2901
|
emitShowLauncher();
|
|
2545
2902
|
}, 120);
|
|
@@ -3530,6 +3887,51 @@ window.__ModuleLoader__.load({
|
|
|
3530
3887
|
return typeof value === "string" && value.trim() ? value.trim() : AUTO_OPEN_TOOL;
|
|
3531
3888
|
}
|
|
3532
3889
|
//#endregion
|
|
3890
|
+
//#region src/client/ui/SideEditorTab.ts
|
|
3891
|
+
/**
|
|
3892
|
+
* dsh-vscode-mode client — SideEditorTab:betterSidebar「文件编辑」Tab 的组件包装。
|
|
3893
|
+
* 把 TabComponentProps(scope/tab/visible)映射为 EditorView 侧栏形态 props,
|
|
3894
|
+
* 并按会话 key 保证切会话状态干净重建;创建种子的初始打开在挂载后投递一次。
|
|
3895
|
+
* 作者 ddj 2026年08月25号
|
|
3896
|
+
*/
|
|
3897
|
+
/**
|
|
3898
|
+
* 侧边栏 Tab 组件(TabDescriptor.component 装配)。
|
|
3899
|
+
* @param props TabComponentProps(scope.sessionId、tab.path/meta 等)
|
|
3900
|
+
* @returns EditorView 侧栏形态
|
|
3901
|
+
*/
|
|
3902
|
+
function SideEditorTab(props) {
|
|
3903
|
+
const sessionId = props?.scope?.sessionId;
|
|
3904
|
+
const initial = react.default.useMemo(() => resolveInitialOpen(props?.tab), [props?.tab]);
|
|
3905
|
+
const dispatchedRef = react.default.useRef(false);
|
|
3906
|
+
react.default.useEffect(() => {
|
|
3907
|
+
setSideEditorMounted(true);
|
|
3908
|
+
return () => setSideEditorMounted(false);
|
|
3909
|
+
}, []);
|
|
3910
|
+
react.default.useEffect(() => {
|
|
3911
|
+
if (dispatchedRef.current) return;
|
|
3912
|
+
dispatchedRef.current = true;
|
|
3913
|
+
const request = takePendingSideOpen(sessionId) ?? initial;
|
|
3914
|
+
window.dispatchEvent(new CustomEvent("edrv:open-editor", { detail: {
|
|
3915
|
+
path: request?.path ?? null,
|
|
3916
|
+
focusDiff: request?.focusDiff === true
|
|
3917
|
+
} }));
|
|
3918
|
+
}, [
|
|
3919
|
+
initial.path,
|
|
3920
|
+
initial.focusDiff,
|
|
3921
|
+
sessionId
|
|
3922
|
+
]);
|
|
3923
|
+
return react.default.createElement(EditorView, {
|
|
3924
|
+
key: sessionId,
|
|
3925
|
+
sessionId,
|
|
3926
|
+
layout: "side",
|
|
3927
|
+
schedule: props?.schedule,
|
|
3928
|
+
addToConversation: props?.addToConversation,
|
|
3929
|
+
sidebarPanels: props?.sidebarPanels,
|
|
3930
|
+
outlineSources: props?.outlineSources,
|
|
3931
|
+
fileMenuItems: props?.fileMenuItems
|
|
3932
|
+
});
|
|
3933
|
+
}
|
|
3934
|
+
//#endregion
|
|
3533
3935
|
//#region src/client/addToConversation.ts
|
|
3534
3936
|
/** DSH reference source 名(dsh-client-ui-reference 注册的 @file/@session 统一源)。 */
|
|
3535
3937
|
const REF_SOURCE = "reference";
|
|
@@ -3708,17 +4110,144 @@ window.__ModuleLoader__.load({
|
|
|
3708
4110
|
};
|
|
3709
4111
|
}
|
|
3710
4112
|
//#endregion
|
|
4113
|
+
//#region src/client/ui/ContextMenu.ts
|
|
4114
|
+
/**
|
|
4115
|
+
* dsh-vscode-mode client — 通用浮动右键菜单(createElement 风格、类型化)。
|
|
4116
|
+
* 全屏 backdrop(点击/右键/Esc 关闭)+ 固定定位(viewport clamp 防越界),
|
|
4117
|
+
* 条目支持 danger/disabled/separator,复用既有 edrv-ctxmenu* 样式类。
|
|
4118
|
+
* 作者 ddj 2026-08-27
|
|
4119
|
+
*/
|
|
4120
|
+
/** 菜单估算宽高(clamp 防越出视口,与 EditorView menuPos 常量对齐)。 */
|
|
4121
|
+
const MENU_W = 224;
|
|
4122
|
+
const MENU_H = 176;
|
|
4123
|
+
/**
|
|
4124
|
+
* 浮动右键菜单。
|
|
4125
|
+
* @param props.x 视口 x 坐标
|
|
4126
|
+
* @param props.y 视口 y 坐标
|
|
4127
|
+
* @param props.entries 菜单项列表
|
|
4128
|
+
* @param props.onClose 关闭回调(backdrop 点击/右键/Esc/点击项后触发)
|
|
4129
|
+
*/
|
|
4130
|
+
function ContextMenu(props) {
|
|
4131
|
+
const { x, y, entries, onClose } = props;
|
|
4132
|
+
react.default.useEffect(() => {
|
|
4133
|
+
const onKey = (e) => {
|
|
4134
|
+
if (e.key === "Escape") onClose();
|
|
4135
|
+
};
|
|
4136
|
+
window.addEventListener("keydown", onKey, true);
|
|
4137
|
+
return () => window.removeEventListener("keydown", onKey, true);
|
|
4138
|
+
}, [onClose]);
|
|
4139
|
+
const left = Math.max(4, Math.min(x, (window.innerWidth || 800) - MENU_W));
|
|
4140
|
+
const top = Math.max(4, Math.min(y, (window.innerHeight || 600) - MENU_H));
|
|
4141
|
+
const children = [];
|
|
4142
|
+
for (const entry of entries) {
|
|
4143
|
+
if (entry.separator) {
|
|
4144
|
+
children.push(react.default.createElement("div", {
|
|
4145
|
+
key: "sep-" + entry.id,
|
|
4146
|
+
className: "edrv-ctxmenu-sep"
|
|
4147
|
+
}));
|
|
4148
|
+
continue;
|
|
4149
|
+
}
|
|
4150
|
+
const cls = "edrv-ctxmenu-item" + (entry.danger ? " edrv-ctxmenu-danger" : "") + (entry.disabled ? " edrv-ctxmenu-disabled" : "");
|
|
4151
|
+
children.push(react.default.createElement("button", {
|
|
4152
|
+
key: entry.id,
|
|
4153
|
+
className: cls,
|
|
4154
|
+
disabled: entry.disabled,
|
|
4155
|
+
onClick: () => {
|
|
4156
|
+
if (!entry.disabled) {
|
|
4157
|
+
entry.onClick?.();
|
|
4158
|
+
onClose();
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
}, entry.label));
|
|
4162
|
+
}
|
|
4163
|
+
return react.default.createElement(react.default.Fragment, null, react.default.createElement("div", {
|
|
4164
|
+
className: "edrv-ctxmenu-backdrop",
|
|
4165
|
+
style: {
|
|
4166
|
+
position: "fixed",
|
|
4167
|
+
inset: 0,
|
|
4168
|
+
zIndex: 70
|
|
4169
|
+
},
|
|
4170
|
+
onClick: onClose,
|
|
4171
|
+
onContextMenu: (e) => {
|
|
4172
|
+
e.preventDefault();
|
|
4173
|
+
onClose();
|
|
4174
|
+
}
|
|
4175
|
+
}), react.default.createElement("div", {
|
|
4176
|
+
className: "edrv-ctxmenu",
|
|
4177
|
+
style: {
|
|
4178
|
+
left,
|
|
4179
|
+
top
|
|
4180
|
+
}
|
|
4181
|
+
}, ...children));
|
|
4182
|
+
}
|
|
4183
|
+
//#endregion
|
|
4184
|
+
//#region src/client/sidebar/contextMenu.ts
|
|
4185
|
+
/** 校验菜单项并写入注册表(缺 id/run/label 抛 TypeError)。 */
|
|
4186
|
+
function itemRegister(entries, notify, item) {
|
|
4187
|
+
if (!item.id || typeof item.run !== "function" || !item.label) throw new TypeError("文件右键菜单项必须提供 id、label 和 run");
|
|
4188
|
+
entries.set(item.id, item);
|
|
4189
|
+
notify();
|
|
4190
|
+
}
|
|
4191
|
+
/**
|
|
4192
|
+
* 创建生命周期独立的右键菜单项注册表。
|
|
4193
|
+
* @author ddj 2026年08月27号
|
|
4194
|
+
* @returns 菜单项注册表
|
|
4195
|
+
*/
|
|
4196
|
+
function createTreeMenuRegistry() {
|
|
4197
|
+
const entries = /* @__PURE__ */ new Map();
|
|
4198
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
4199
|
+
const notify = () => {
|
|
4200
|
+
for (const listener of listeners) listener();
|
|
4201
|
+
};
|
|
4202
|
+
const list = () => [...entries.values()].sort((a, b) => (a.order ?? 100) - (b.order ?? 100));
|
|
4203
|
+
return {
|
|
4204
|
+
register(item) {
|
|
4205
|
+
itemRegister(entries, notify, item);
|
|
4206
|
+
return () => {
|
|
4207
|
+
if (entries.get(item.id) !== item) return;
|
|
4208
|
+
entries.delete(item.id);
|
|
4209
|
+
notify();
|
|
4210
|
+
};
|
|
4211
|
+
},
|
|
4212
|
+
list,
|
|
4213
|
+
subscribe(listener) {
|
|
4214
|
+
listeners.add(listener);
|
|
4215
|
+
return () => listeners.delete(listener);
|
|
4216
|
+
},
|
|
4217
|
+
get: (id) => entries.get(id)
|
|
4218
|
+
};
|
|
4219
|
+
}
|
|
4220
|
+
/**
|
|
4221
|
+
* 按目标构建当前可见菜单项(visible 过滤 + order 排序)。
|
|
4222
|
+
* @author ddj 2026年08月27号
|
|
4223
|
+
* @param registry 菜单项注册表
|
|
4224
|
+
* @param target 右键目标
|
|
4225
|
+
* @param ctx 面板共享上下文
|
|
4226
|
+
* @returns 可见菜单项(已排序)
|
|
4227
|
+
*/
|
|
4228
|
+
function buildTreeMenu(registry, target, ctx) {
|
|
4229
|
+
if (!registry) return [];
|
|
4230
|
+
const out = [];
|
|
4231
|
+
for (const item of registry.list()) {
|
|
4232
|
+
if (typeof item.visible === "function" && !item.visible(target, ctx)) continue;
|
|
4233
|
+
out.push(item);
|
|
4234
|
+
}
|
|
4235
|
+
return out;
|
|
4236
|
+
}
|
|
4237
|
+
//#endregion
|
|
3711
4238
|
//#region src/client/sidebar/panels/FileExplorer.ts
|
|
3712
4239
|
/**
|
|
3713
4240
|
* dsh-vscode-mode client — 侧边栏「文件管理」面板(懒加载目录树)。
|
|
3714
4241
|
* 点目录展开/收起(首次经 edrv.listDir 拉取并缓存),点文件经 ctx.openFile 打开;
|
|
3715
4242
|
* 差异角标取 pendingByPath,活动文件高亮;edrv:refresh 事件与手动刷新重载树。
|
|
3716
|
-
*
|
|
4243
|
+
* 右键行/空白弹出菜单:项来自 ctx.fileMenuItems 注册表(可拓展),
|
|
4244
|
+
* 内置「在文件浏览器中打开」经 edrv.revealInExplorer 定位/打开。
|
|
4245
|
+
* 作者 ddj 2026-08-26 / 2026-08-27
|
|
3717
4246
|
*/
|
|
3718
4247
|
const DIR_CAP = 4e3;
|
|
3719
4248
|
/**
|
|
3720
4249
|
* 目录树面板主体。
|
|
3721
|
-
* @param props.ctx 面板共享上下文(sessionId/openFile/activePath/pendingByPath)
|
|
4250
|
+
* @param props.ctx 面板共享上下文(sessionId/openFile/activePath/pendingByPath/fileMenuItems/notify)
|
|
3722
4251
|
*/
|
|
3723
4252
|
function FileExplorer(props) {
|
|
3724
4253
|
const ctx = props?.ctx;
|
|
@@ -3731,6 +4260,7 @@ window.__ModuleLoader__.load({
|
|
|
3731
4260
|
const [expanded, setExpanded] = react.default.useState({});
|
|
3732
4261
|
const [loading, setLoading] = react.default.useState({});
|
|
3733
4262
|
const [error, setError] = react.default.useState(null);
|
|
4263
|
+
const [menu, setMenu] = react.default.useState(null);
|
|
3734
4264
|
const tokensRef = react.default.useRef({});
|
|
3735
4265
|
const expandedRef = react.default.useRef({});
|
|
3736
4266
|
expandedRef.current = expanded;
|
|
@@ -3809,6 +4339,18 @@ window.__ModuleLoader__.load({
|
|
|
3809
4339
|
onClick: () => {
|
|
3810
4340
|
if (isDir) toggle(e.path);
|
|
3811
4341
|
else openFile(e.path);
|
|
4342
|
+
},
|
|
4343
|
+
onContextMenu: (ev) => {
|
|
4344
|
+
ev.preventDefault();
|
|
4345
|
+
ev.stopPropagation();
|
|
4346
|
+
setMenu({
|
|
4347
|
+
x: ev.clientX,
|
|
4348
|
+
y: ev.clientY,
|
|
4349
|
+
target: {
|
|
4350
|
+
path: e.path,
|
|
4351
|
+
type: e.type
|
|
4352
|
+
}
|
|
4353
|
+
});
|
|
3812
4354
|
}
|
|
3813
4355
|
}, react.default.createElement("span", { className: "edrv-tree-chev" }, isDir ? isOpen ? "▾" : "▸" : ""), react.default.createElement("span", { className: "edrv-tree-name" + (dim ? " edrv-tree-dim" : "") }, isDir ? isOpen ? "📂" : "📁" : "📄", " ", e.name), pending > 0 ? react.default.createElement("span", { className: "edrv-tree-badge" }, String(pending)) : null);
|
|
3814
4356
|
};
|
|
@@ -3835,7 +4377,29 @@ window.__ModuleLoader__.load({
|
|
|
3835
4377
|
}, "目录条目过多,仅显示前 4000 项"));
|
|
3836
4378
|
return rows;
|
|
3837
4379
|
};
|
|
3838
|
-
|
|
4380
|
+
const onPanelContext = (ev) => {
|
|
4381
|
+
ev.preventDefault();
|
|
4382
|
+
setMenu({
|
|
4383
|
+
x: ev.clientX,
|
|
4384
|
+
y: ev.clientY,
|
|
4385
|
+
target: {
|
|
4386
|
+
path: "",
|
|
4387
|
+
type: "directory"
|
|
4388
|
+
}
|
|
4389
|
+
});
|
|
4390
|
+
};
|
|
4391
|
+
const menuEntries = menu ? buildTreeMenu(ctx?.fileMenuItems, menu.target, ctx).map((item) => ({
|
|
4392
|
+
id: item.id,
|
|
4393
|
+
label: item.label,
|
|
4394
|
+
danger: item.danger,
|
|
4395
|
+
disabled: item.disabled,
|
|
4396
|
+
separator: item.separator,
|
|
4397
|
+
onClick: () => item.run(menu.target, ctx)
|
|
4398
|
+
})) : [];
|
|
4399
|
+
return react.default.createElement("div", {
|
|
4400
|
+
className: "edrv-side-panel",
|
|
4401
|
+
onContextMenu: onPanelContext
|
|
4402
|
+
}, react.default.createElement("div", { className: "edrv-side-head" }, react.default.createElement("span", { className: "edrv-side-title" }, "资源管理器"), react.default.createElement("span", {
|
|
3839
4403
|
className: "edrv-side-root",
|
|
3840
4404
|
title: root || ""
|
|
3841
4405
|
}, rootName), react.default.createElement("span", { style: { flex: 1 } }), react.default.createElement("button", {
|
|
@@ -3845,7 +4409,12 @@ window.__ModuleLoader__.load({
|
|
|
3845
4409
|
}, "⟳")), react.default.createElement("div", { className: "edrv-tree" }, error ? react.default.createElement("div", { className: "edrv-tree-error" }, react.default.createElement("span", null, String(error)), react.default.createElement("button", {
|
|
3846
4410
|
className: "edrv-side-btn",
|
|
3847
4411
|
onClick: () => refresh()
|
|
3848
|
-
}, "重试")) : null, rowsOf("", 0))
|
|
4412
|
+
}, "重试")) : null, rowsOf("", 0)), menu && menuEntries.length ? react.default.createElement(ContextMenu, {
|
|
4413
|
+
x: menu.x,
|
|
4414
|
+
y: menu.y,
|
|
4415
|
+
entries: menuEntries,
|
|
4416
|
+
onClose: () => setMenu(null)
|
|
4417
|
+
}) : null);
|
|
3849
4418
|
}
|
|
3850
4419
|
//#endregion
|
|
3851
4420
|
//#region src/client/sidebar/panels/index.ts
|
|
@@ -3869,6 +4438,31 @@ window.__ModuleLoader__.load({
|
|
|
3869
4438
|
};
|
|
3870
4439
|
}
|
|
3871
4440
|
//#endregion
|
|
4441
|
+
//#region src/client/sidebar/menuItems.ts
|
|
4442
|
+
/**
|
|
4443
|
+
* dsh-vscode-mode client — 文件管理右键菜单内置项。
|
|
4444
|
+
* 首个内置项:「在文件浏览器中打开」(文件→OS Explorer 定位选中、目录→打开目录)。
|
|
4445
|
+
* 反馈统一走 ctx.notify(由 EditorView 提供,落到编辑区路径栏状态)。
|
|
4446
|
+
* 作者 ddj 2026-08-27
|
|
4447
|
+
*/
|
|
4448
|
+
/**
|
|
4449
|
+
* 构造内置右键菜单项列表(后续内置项直接追加)。
|
|
4450
|
+
* @author ddj 2026年08月27号
|
|
4451
|
+
* @returns 内置菜单项数组
|
|
4452
|
+
*/
|
|
4453
|
+
function createDefaultFileMenuItems() {
|
|
4454
|
+
return [{
|
|
4455
|
+
id: "reveal-in-explorer",
|
|
4456
|
+
label: "在文件浏览器中打开",
|
|
4457
|
+
order: 0,
|
|
4458
|
+
run: (target, ctx) => {
|
|
4459
|
+
revealInExplorer(ctx.sessionId, target.path).then((outcome) => {
|
|
4460
|
+
ctx.notify?.(outcome.ok ? "已在文件浏览器中打开" : "打开失败:" + (outcome.error ?? "未知错误"));
|
|
4461
|
+
});
|
|
4462
|
+
}
|
|
4463
|
+
}];
|
|
4464
|
+
}
|
|
4465
|
+
//#endregion
|
|
3872
4466
|
//#region src/client/outline/parse.ts
|
|
3873
4467
|
/** monaco SymbolKind 数值常量(与 LSP SymbolKind 一致,面板渲染按此分组)。 */
|
|
3874
4468
|
const SK = {
|
|
@@ -4603,7 +5197,8 @@ window.__ModuleLoader__.load({
|
|
|
4603
5197
|
//#region src/client/index.ts
|
|
4604
5198
|
/**
|
|
4605
5199
|
* dsh-vscode-mode client — 浏览器半入口:slot 注册 + 装配。
|
|
4606
|
-
* 挂点:
|
|
5200
|
+
* 挂点:betterSidebar「文件编辑」Tab(侧边栏形态,对话+编辑同屏;未装 dsh-better-sidebar 时
|
|
5201
|
+
* 回退 conversation.view 中央页签)+ conversation.input.dock 差异条 + header 差异角标。
|
|
4607
5202
|
* 与 Host 通信:同源 fetch('/edrv/rpc')(shared/rpc 契约)。
|
|
4608
5203
|
*
|
|
4609
5204
|
* ⚠️ 跨版本 slot 装配(2026-08-21):新版 DSH 的 slots 系统要求 slot 必须由父 entry
|
|
@@ -4656,6 +5251,8 @@ window.__ModuleLoader__.load({
|
|
|
4656
5251
|
const binder = pickSettingsBinder(ctx);
|
|
4657
5252
|
const settings = binder.scope;
|
|
4658
5253
|
let selected = autoValue("auto");
|
|
5254
|
+
/** 可选探测 betterSidebar 服务(不进 inject:缺失会让插件停靠等待,杀死回退路径)。 */
|
|
5255
|
+
const sideService = detectSidebarService(ctx);
|
|
4659
5256
|
/** 「添加到对话」动作集:编辑区/Tab 右键菜单注入文件引用与代码块(conversation 服务缺失时各动作安全降级)。 */
|
|
4660
5257
|
const addToConversation = createAddToConversation(ctx);
|
|
4661
5258
|
/** 客户端侧兼容摘要(与 host 报告合并展示;惰性求值保证 HMR 后仍新鲜)。 */
|
|
@@ -4674,6 +5271,11 @@ window.__ModuleLoader__.load({
|
|
|
4674
5271
|
name: "侧边栏打开器(dsh-better-sidebar)",
|
|
4675
5272
|
active: registry.get(SIDEBAR_PLUGIN) !== void 0,
|
|
4676
5273
|
note: registry.get("dsh-better-sidebar") !== void 0 ? "已注册(优先级 80)" : "未检测到侧边栏打开能力"
|
|
5274
|
+
},
|
|
5275
|
+
{
|
|
5276
|
+
name: "侧边栏编辑区(dsh-better-sidebar)",
|
|
5277
|
+
active: sideService !== void 0,
|
|
5278
|
+
note: sideService !== void 0 ? "编辑区=侧边栏 Tab(对话+编辑同屏)" : "未检测到;安装 dsh-better-sidebar 后刷新启用侧边栏形态(dsh plugin --profile web add dsh-better-sidebar)"
|
|
4677
5279
|
}
|
|
4678
5280
|
];
|
|
4679
5281
|
ctx.provide("fileOpeners", registry);
|
|
@@ -4681,6 +5283,9 @@ window.__ModuleLoader__.load({
|
|
|
4681
5283
|
const sidebarPanels = createSidebarPanelRegistry();
|
|
4682
5284
|
ctx.provide("edrvSidebarPanels", sidebarPanels);
|
|
4683
5285
|
ctx.effect(() => sidebarPanels.register(createFilePanel()), "vscode-mode: sidebar panel");
|
|
5286
|
+
const fileMenuItems = createTreeMenuRegistry();
|
|
5287
|
+
ctx.provide("edrvFileContextMenuItems", fileMenuItems);
|
|
5288
|
+
for (const item of createDefaultFileMenuItems()) ctx.effect(() => fileMenuItems.register(item), "vscode-mode: file context menu item " + item.id);
|
|
4684
5289
|
const outlineSources = createOutlineSourceRegistry();
|
|
4685
5290
|
ctx.provide("edrvOutlineSources", outlineSources);
|
|
4686
5291
|
ctx.effect(() => registerBuiltinOutlineSources(outlineSources), "vscode-mode: outline sources");
|
|
@@ -4720,18 +5325,47 @@ window.__ModuleLoader__.load({
|
|
|
4720
5325
|
},
|
|
4721
5326
|
logger: (message) => console.warn("[dsh-vscode-mode] " + message)
|
|
4722
5327
|
}), "vscode-mode: file link routing");
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
5328
|
+
const registerLegacyTab = () => {
|
|
5329
|
+
registerSlotSafely(ctx, {
|
|
5330
|
+
name: "conversation.view",
|
|
5331
|
+
id: "edrv-editor",
|
|
5332
|
+
order: 5,
|
|
5333
|
+
label: "文件编辑",
|
|
5334
|
+
inject: (sessionId) => ({ sessionId })
|
|
5335
|
+
}, (props) => react.default.createElement(EditorView, Object.assign({}, props, {
|
|
5336
|
+
layout: "tab",
|
|
5337
|
+
sideHint: SIDEBAR_INSTALL_CMD,
|
|
5338
|
+
schedule,
|
|
5339
|
+
addToConversation,
|
|
5340
|
+
sidebarPanels,
|
|
5341
|
+
outlineSources,
|
|
5342
|
+
fileMenuItems
|
|
5343
|
+
})));
|
|
5344
|
+
};
|
|
5345
|
+
if (sideService) ctx.effect(() => installSideEditor({
|
|
5346
|
+
service: sideService,
|
|
5347
|
+
renderTab: (props) => react.default.createElement(SideEditorTab, Object.assign({}, props, {
|
|
5348
|
+
schedule,
|
|
5349
|
+
addToConversation,
|
|
5350
|
+
sidebarPanels,
|
|
5351
|
+
outlineSources,
|
|
5352
|
+
fileMenuItems
|
|
5353
|
+
})),
|
|
5354
|
+
activeSession: () => {
|
|
5355
|
+
const snapshot = sessions?.list?.getSnapshot?.();
|
|
5356
|
+
const sessionId = snapshot?.current;
|
|
5357
|
+
if (!sessionId) return void 0;
|
|
5358
|
+
return {
|
|
5359
|
+
sessionId,
|
|
5360
|
+
cwd: snapshot?.byId?.[sessionId]?.cwd
|
|
5361
|
+
};
|
|
5362
|
+
},
|
|
5363
|
+
registerLegacyFallback: registerLegacyTab
|
|
5364
|
+
}), "vscode-mode: sidebar editor tab");
|
|
5365
|
+
else {
|
|
5366
|
+
setEnsureSideEditor(null);
|
|
5367
|
+
registerLegacyTab();
|
|
5368
|
+
}
|
|
4735
5369
|
registerSlotSafely(ctx, {
|
|
4736
5370
|
name: "conversation.input.dock",
|
|
4737
5371
|
id: "edrv-diff-dock",
|