dsh-diff-approval 0.7.0 → 0.8.0
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 +18 -10
- package/README.zh.md +18 -10
- package/docs/images/pending-panel.png +0 -0
- package/docs/images/pending-panel.zh.png +0 -0
- package/lib/client.js +772 -193
- package/lib/index.js +614 -13
- package/lib/types/client/PendingPanel.d.ts +11 -1
- package/lib/types/client/SettingsTab.d.ts +11 -0
- package/lib/types/client/locales.d.ts +34 -0
- package/lib/types/client/port.d.ts +7 -1
- package/lib/types/client/settings.d.ts +19 -0
- package/lib/types/client/slots.d.ts +11 -1
- package/lib/types/client/store.d.ts +7 -1
- package/lib/types/pending.d.ts +12 -0
- package/lib/types/types.d.ts +13 -2
- package/lib/types/vcs.d.ts +89 -0
- package/package.json +3 -1
package/lib/client.js
CHANGED
|
@@ -11620,8 +11620,39 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11620
11620
|
return `${referencePathOf(path, workspacePath)}:${lineRangeLabel(start, end)}`;
|
|
11621
11621
|
}
|
|
11622
11622
|
//#endregion
|
|
11623
|
+
//#region lib/types/client/settings.js
|
|
11624
|
+
/** Client preferences for the review panel, persisted in localStorage. */
|
|
11625
|
+
const PASTE_ON_COPY_KEY = "diff-approval:paste-on-copy";
|
|
11626
|
+
const IMPORT_UNTRACKED_KEY = "diff-approval:import-untracked";
|
|
11627
|
+
/**
|
|
11628
|
+
* Whether copying a reference should also paste it into the chat input and
|
|
11629
|
+
* focus it. Defaults to on; only an explicit `'0'` disables it.
|
|
11630
|
+
* @returns whether auto-paste is enabled.
|
|
11631
|
+
*/
|
|
11632
|
+
function pasteOnCopyEnabled() {
|
|
11633
|
+
return localStorage.getItem(PASTE_ON_COPY_KEY) !== "0";
|
|
11634
|
+
}
|
|
11635
|
+
/** Persist the auto-paste preference. */
|
|
11636
|
+
function setPasteOnCopyEnabled(value) {
|
|
11637
|
+
localStorage.setItem(PASTE_ON_COPY_KEY, value ? "1" : "0");
|
|
11638
|
+
}
|
|
11639
|
+
/**
|
|
11640
|
+
* Whether importing workspace VCS changes includes new/untracked files (git
|
|
11641
|
+
* `??`, svn `?`, p4 unversioned). Defaults to off: collecting them scans the
|
|
11642
|
+
* whole workspace, which can be slow on large trees, so the preference is
|
|
11643
|
+
* opt-in. Only an explicit `'1'` enables it.
|
|
11644
|
+
* @returns whether untracked files are imported.
|
|
11645
|
+
*/
|
|
11646
|
+
function includeUntrackedEnabled() {
|
|
11647
|
+
return localStorage.getItem(IMPORT_UNTRACKED_KEY) === "1";
|
|
11648
|
+
}
|
|
11649
|
+
/** Persist the import-untracked preference. */
|
|
11650
|
+
function setIncludeUntrackedEnabled(value) {
|
|
11651
|
+
localStorage.setItem(IMPORT_UNTRACKED_KEY, value ? "1" : "0");
|
|
11652
|
+
}
|
|
11653
|
+
//#endregion
|
|
11623
11654
|
//#region \0dsh-css:/home/runner/work/dsh-diff-approval/dsh-diff-approval/src/client/PendingPanel.module.css.mjs
|
|
11624
|
-
const css = ".F1KBNa_layer{box-sizing:border-box;flex:none;align-items:center;width:calc(100% + 8px);height:42px;margin:4px -4px;display:flex;position:relative}.F1KBNa_footerButtons{align-items:center;width:100%;display:flex}.F1KBNa_badge{box-sizing:border-box;width:100%;height:42px;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:none;border-radius:12px;align-items:center;gap:8px;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;display:flex;overflow:hidden}.F1KBNa_badge:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_badge[data-active]{background:var(--dsw-alias-interactive-bg-hover-solid)}.F1KBNa_badgeLabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.F1KBNa_badgeCount{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;margin-left:auto;font-size:12px;line-height:16px}.F1KBNa_layer.F1KBNa_rail{width:36px;height:36px;margin:8px 0 10px}.F1KBNa_rail .F1KBNa_badge{border-radius:50%;justify-content:center;gap:0;width:36px;height:36px;padding:0}.F1KBNa_rail .F1KBNa_badgeLabel{display:none}.F1KBNa_rail .F1KBNa_badgeCount{box-sizing:border-box;background:var(--dsw-alias-state-business-primary);min-width:18px;height:18px;color:var(--dsw-alias-label-primary-foreground);font-variant-numeric:tabular-nums;border-radius:9px;justify-content:center;align-items:center;padding:0 4px;font-size:11px;line-height:18px;display:flex;position:absolute;top:-3px;right:-7px}.F1KBNa_panel{z-index:30;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:auto;max-width:none;box-shadow:var(--dsw-shadow-lv2);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:12px;flex-direction:column;display:flex;position:fixed;inset:8px 8px 128px;overflow:hidden}.F1KBNa_header{box-sizing:border-box;border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);flex:none;justify-content:space-between;align-items:center;min-height:44px;padding:10px 12px;display:flex}.F1KBNa_headerActions{align-items:center;gap:2px;display:flex}.F1KBNa_states{flex:1;min-height:0;padding:4px 12px 12px;overflow-y:auto}.F1KBNa_split{flex:1;align-items:stretch;min-height:0;display:flex}.F1KBNa_fileList{box-sizing:border-box;border-right:1px solid var(--dsw-alias-border-l2);flex:none;width:240px;min-height:0;padding:4px 8px 12px;overflow-y:auto}.F1KBNa_resizeHandle{cursor:col-resize;background:0 0;flex:none;width:5px;margin:0 -2px}.F1KBNa_resizeHandle:hover{background:var(--dsw-alias-border-l2)}.F1KBNa_detail{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}.F1KBNa_detailEmpty{color:var(--dsw-alias-label-tertiary);text-align:center;flex:1;justify-content:center;align-items:center;margin:0;padding:24px;font-size:12px;line-height:18px;display:flex}.F1KBNa_title{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:20px}.F1KBNa_note,.F1KBNa_readError,.F1KBNa_hint{color:var(--dsw-alias-label-tertiary);margin:4px 0;font-size:12px;line-height:18px}.F1KBNa_readError{color:var(--dsw-alias-state-error-primary)}.F1KBNa_group{color:var(--dsw-alias-label-tertiary);margin:8px 0 4px;font-size:12px;font-weight:500;line-height:16px}.F1KBNa_rows{margin:0;padding:0;list-style:none}.F1KBNa_row{border:1px solid #0000;border-radius:10px;margin:2px 0}.F1KBNa_rowHead{width:100%;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:10px;align-items:baseline;gap:8px;padding:6px 8px;display:flex}.F1KBNa_rowHead:hover{background:var(--dsw-alias-interactive-bg-hover-solid)}.F1KBNa_rowHead[data-selected]{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_rowPath{text-overflow:ellipsis;white-space:nowrap;min-width:0;font:var(--dsw-font-markdown-code-block);overflow:hidden}.F1KBNa_kindTag{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);white-space:nowrap;border-radius:6px;flex:none;padding:1px 6px;font-size:11px;line-height:14px}.F1KBNa_kindHint{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px;line-height:16px}.F1KBNa_divergedHint,.F1KBNa_missingHint{border-bottom:1px solid var(--dsw-alias-border-l2);margin:0;padding:6px 8px;font-size:12px;line-height:18px}.F1KBNa_missing{border:1px solid var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-state-warn-label,var(--dsw-alias-state-warn-primary));white-space:nowrap;border-radius:6px;flex:none;padding:1px 6px;font-size:11px;line-height:14px}.F1KBNa_missingHint{color:var(--dsw-alias-state-warn-label,var(--dsw-alias-state-warn-primary))}.F1KBNa_rowMeta{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;gap:6px;margin-left:auto;font-size:12px;line-height:16px;display:inline-flex}.F1KBNa_addCount{color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 60%, var(--dsw-alias-label-primary))}.F1KBNa_delCount{color:color-mix(in srgb, var(--dsw-alias-state-error-primary) 60%, var(--dsw-alias-label-primary))}.F1KBNa_diff{background:var(--dsw-alias-markdown-code-block);flex-direction:column;flex:1;min-height:0;display:flex;position:relative;overflow:hidden}.F1KBNa_diffHeader{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:6px 8px;display:flex}.F1KBNa_diffPath{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-primary);font:var(--dsw-font-markdown-code-block);flex:1;font-size:12px;line-height:18px;overflow:hidden}.F1KBNa_diffActions{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:6px 8px;display:flex}.F1KBNa_diffStats{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:12px;line-height:16px}.F1KBNa_flexSpacer{flex:1}.F1KBNa_action{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;padding:3px 12px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_action:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_action:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.F1KBNa_actionPrimary{background:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50)}.F1KBNa_actionPrimary:hover:not(:disabled){background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 85%, var(--dsw-static-neutral-bluish-1000))}.F1KBNa_actionPrimary:disabled{background:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50);opacity:.55}.F1KBNa_iconAction{justify-content:center;align-items:center;min-height:25px;padding:4px 6px;display:inline-flex}.F1KBNa_close{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:28px;justify-content:center;align-items:center;padding:0;display:inline-flex}.F1KBNa_close:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.F1KBNa_expand{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:28px;justify-content:center;align-items:center;padding:0;display:inline-flex}.F1KBNa_expand:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.F1KBNa_expandExpanded svg{transform:rotate(180deg)}.F1KBNa_diffBodyWrap{flex:1;min-height:0;display:flex;position:relative}.F1KBNa_diffBody{min-width:0;font:var(--dsw-font-markdown-code-block);cursor:text;flex:1;padding:0;position:relative;overflow:auto}.F1KBNa_diffBody::-webkit-scrollbar,.F1KBNa_diffBody::-webkit-scrollbar-track,.F1KBNa_diffBody::-webkit-scrollbar-thumb{cursor:default}.F1KBNa_blockActions{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-markdown-code-block);box-shadow:var(--dsw-shadow-lv1);z-index:2;border-radius:10px;align-items:center;gap:9px;padding:5px;display:flex;position:absolute;right:8px}.F1KBNa_blockPosition{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;margin-top:1px;margin-left:7px;font-size:12px;line-height:16px}.F1KBNa_searchBar{z-index:3;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-markdown-code-block);box-shadow:var(--dsw-shadow-lv1);border-radius:10px;align-items:center;gap:4px;padding:4px;display:flex;position:absolute;top:8px;right:8px}.F1KBNa_searchInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);width:150px;color:var(--dsw-alias-label-primary);border-radius:6px;outline:none;padding:3px 8px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_searchInput:focus{border-color:var(--dsw-alias-state-business-primary)}.F1KBNa_searchCount{text-align:center;min-width:34px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:12px;line-height:16px}.F1KBNa_diffBody [data-diff-search=hit]{background-image:linear-gradient(#facc1529,#facc1529)}.F1KBNa_diffBody [data-diff-search=current]{background-image:linear-gradient(#facc1552,#facc1552)}.F1KBNa_overviewRuler{pointer-events:none;opacity:.5;width:4px;position:absolute;top:0;bottom:0;right:0}.F1KBNa_overviewMarker{border-radius:2px;width:100%;min-height:2px;position:absolute;right:0}.F1KBNa_markerDel{background-color:var(--dsw-alias-state-error-primary)}.F1KBNa_markerAdd{background-color:var(--dsw-alias-state-success-primary)}.F1KBNa_lines{border-spacing:0;width:max-content;min-width:100%;display:table}.F1KBNa_line{height:22px;line-height:22px;display:table-row}.F1KBNa_vSpacer{display:table-row}.F1KBNa_gutter{box-sizing:border-box;text-align:right;width:44px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;user-select:none;cursor:default;padding-right:10px;display:table-cell}.F1KBNa_code{white-space:pre;display:table-cell}.F1KBNa_context{color:var(--dsw-alias-label-primary)}.F1KBNa_del{background-color:color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent)}.F1KBNa_add{background-color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 10%, transparent)}.F1KBNa_statusBar{box-sizing:border-box;border-top:1px solid var(--dsw-alias-border-l2);height:34px;color:var(--dsw-alias-label-tertiary);font-family:var(--dsw-font-markdown-code-block);font-variant-numeric:tabular-nums;flex:none;align-items:center;padding:0 8px;font-size:12px;line-height:18px;display:flex}.F1KBNa_statusAction{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);white-space:nowrap;cursor:pointer;background:0 0;border-radius:8px;padding:3px 12px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_statusAction:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_langSelect{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;flex:none;align-items:center;gap:4px;padding:3px 12px;font-family:inherit;font-size:12px;line-height:18px;display:inline-flex}.F1KBNa_langSelect:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_langLabel{text-overflow:ellipsis;white-space:nowrap;max-width:140px;overflow:hidden}";
|
|
11655
|
+
const css = ".F1KBNa_layer{box-sizing:border-box;flex:none;align-items:center;width:calc(100% + 4px);height:42px;margin:4px -2px;display:flex;position:relative}.F1KBNa_footerButtons{align-items:center;width:100%;display:flex}.F1KBNa_badge{box-sizing:border-box;width:100%;height:42px;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:none;border-radius:12px;align-items:center;gap:8px;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;display:flex;overflow:hidden}.F1KBNa_badge:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_badge[data-active]{background:var(--dsw-alias-interactive-bg-hover-solid)}.F1KBNa_badge:disabled{color:var(--dsw-alias-label-tertiary);cursor:default;background:0 0}.F1KBNa_badgeLabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.F1KBNa_badgeCount{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;margin-left:auto;font-size:12px;line-height:16px}.F1KBNa_layer.F1KBNa_rail{width:36px;height:36px;margin:8px 0 10px}.F1KBNa_rail .F1KBNa_badge{border-radius:50%;justify-content:center;gap:0;width:36px;height:36px;padding:0}.F1KBNa_rail .F1KBNa_badgeLabel{display:none}.F1KBNa_rail .F1KBNa_badgeCount{box-sizing:border-box;background:var(--dsw-alias-state-business-primary);min-width:18px;height:18px;color:var(--dsw-alias-label-primary-foreground);font-variant-numeric:tabular-nums;border-radius:9px;justify-content:center;align-items:center;padding:0 4px;font-size:11px;line-height:18px;display:flex;position:absolute;top:-3px;right:-7px}.F1KBNa_fullscreenBackdrop{z-index:29;background:var(--dsw-specific-sidebar-fill);position:fixed;inset:0}.F1KBNa_panel{z-index:30;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:auto;max-width:none;box-shadow:var(--dsw-shadow-lv2);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:12px;flex-direction:column;display:flex;position:fixed;inset:8px 8px 128px;overflow:hidden}.F1KBNa_header{box-sizing:border-box;border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);flex:none;justify-content:space-between;align-items:center;min-height:44px;padding:10px 12px;display:flex}.F1KBNa_headerActions{align-items:center;gap:2px;display:flex}.F1KBNa_settingsPage{padding:8px 12px}.F1KBNa_settingsRow{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:16px 0;display:flex}.F1KBNa_settingsRowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}.F1KBNa_settingsRowTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}.F1KBNa_settingsRowDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}.F1KBNa_settingsSelector{background:var(--dsw-alias-bg-module-platform);height:36px;font:inherit;color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:18px;align-items:center;gap:12px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.F1KBNa_settingsSelector:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_settingsSelectorChevron{flex:none}.F1KBNa_states{flex-direction:column;flex:1;min-height:0;padding:4px 12px 12px;display:flex;overflow-y:auto}.F1KBNa_split{flex:1;align-items:stretch;min-height:0;display:flex}.F1KBNa_fileList{box-sizing:border-box;border-right:1px solid var(--dsw-alias-border-l2);flex-direction:column;flex:none;width:240px;min-height:0;padding:4px 8px 12px;display:flex}.F1KBNa_listScroll{flex:1;min-height:0;overflow-y:auto}.F1KBNa_bulkActions{flex:none;gap:6px;padding-top:8px;display:flex}.F1KBNa_bulkActions .F1KBNa_action{text-align:center;flex:1}.F1KBNa_resizeHandle{cursor:col-resize;background:0 0;flex:none;width:5px;margin:0 -2px}.F1KBNa_resizeHandle:hover{background:var(--dsw-alias-border-l2)}.F1KBNa_detail{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}.F1KBNa_detailEmpty{color:var(--dsw-alias-label-tertiary);text-align:center;flex:1;justify-content:center;align-items:center;margin:0;padding:24px;font-size:12px;line-height:18px;display:flex}.F1KBNa_title{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:20px}.F1KBNa_note,.F1KBNa_readError,.F1KBNa_hint{color:var(--dsw-alias-label-tertiary);margin:4px 0;font-size:12px;line-height:18px}.F1KBNa_noteCentered{text-align:center;margin:auto}.F1KBNa_emptyState{flex-direction:column;align-items:center;gap:10px;margin:auto;display:flex}.F1KBNa_importButton{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;padding:5px 14px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_importButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_importButton:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.F1KBNa_importNote{color:var(--dsw-alias-label-tertiary);text-align:center;margin:0;font-size:12px;line-height:18px}.F1KBNa_readError{color:var(--dsw-alias-state-error-primary)}.F1KBNa_group{color:var(--dsw-alias-label-tertiary);margin:8px 0 4px;font-size:12px;font-weight:500;line-height:16px}.F1KBNa_rows{margin:0;padding:0;list-style:none}.F1KBNa_row{border:1px solid #0000;border-radius:10px;margin:2px 0}.F1KBNa_rowHead{width:100%;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:10px;align-items:baseline;gap:8px;padding:6px 8px;display:flex}.F1KBNa_rowHead:hover{background:var(--dsw-alias-interactive-bg-hover-solid)}.F1KBNa_rowHead[data-selected]{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_rowPath{text-overflow:ellipsis;white-space:nowrap;min-width:0;font:var(--dsw-font-markdown-code-block);overflow:hidden}.F1KBNa_kindTag{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);white-space:nowrap;border-radius:6px;flex:none;padding:1px 6px;font-size:11px;line-height:14px}.F1KBNa_kindHint{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px;line-height:16px}.F1KBNa_divergedHint,.F1KBNa_missingHint{border-bottom:1px solid var(--dsw-alias-border-l2);margin:0;padding:6px 8px;font-size:12px;line-height:18px}.F1KBNa_missing{border:1px solid var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-state-warn-label,var(--dsw-alias-state-warn-primary));white-space:nowrap;border-radius:6px;flex:none;padding:1px 6px;font-size:11px;line-height:14px}.F1KBNa_rowFailed{border:1px solid var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary);white-space:nowrap;border-radius:6px;flex:none;padding:1px 6px;font-size:11px;line-height:14px}.F1KBNa_actionError{border-bottom:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;margin:0;padding:6px 8px;font-size:12px;line-height:18px}.F1KBNa_missingHint{color:var(--dsw-alias-state-warn-label,var(--dsw-alias-state-warn-primary))}.F1KBNa_rowMeta{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;gap:6px;margin-left:auto;font-size:12px;line-height:16px;display:inline-flex}.F1KBNa_addCount{color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 60%, var(--dsw-alias-label-primary))}.F1KBNa_delCount{color:color-mix(in srgb, var(--dsw-alias-state-error-primary) 60%, var(--dsw-alias-label-primary))}.F1KBNa_diff{background:var(--dsw-alias-markdown-code-block);flex-direction:column;flex:1;min-height:0;display:flex;position:relative;overflow:hidden}.F1KBNa_diffHeader{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:6px 8px;display:flex}.F1KBNa_diffPath{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-primary);font:var(--dsw-font-markdown-code-block);flex:1;font-size:12px;line-height:18px;overflow:hidden}.F1KBNa_diffActions{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:6px 8px;display:flex}.F1KBNa_diffStats{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:12px;line-height:16px}.F1KBNa_flexSpacer{flex:1}.F1KBNa_action{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;padding:3px 12px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_action:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_action:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.F1KBNa_actionPrimary{background:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50)}.F1KBNa_actionPrimary:hover:not(:disabled){background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 85%, var(--dsw-static-neutral-bluish-1000))}.F1KBNa_actionPrimary:disabled{background:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50);opacity:.55}.F1KBNa_actionQuietDisabled:disabled{cursor:pointer;color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l1);background:0 0}.F1KBNa_actionPrimary.F1KBNa_actionQuietDisabled:disabled{background:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50);opacity:1}.F1KBNa_iconAction{justify-content:center;align-items:center;min-height:25px;padding:4px 6px;display:inline-flex}.F1KBNa_close{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:28px;justify-content:center;align-items:center;padding:0;display:inline-flex}.F1KBNa_close:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.F1KBNa_expand{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:28px;justify-content:center;align-items:center;padding:0;display:inline-flex}.F1KBNa_expand:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.F1KBNa_expandExpanded svg{transform:rotate(180deg)}.F1KBNa_diffBodyWrap{flex:1;min-height:0;display:flex;position:relative}.F1KBNa_diffBody{min-width:0;font:var(--dsw-font-markdown-code-block);cursor:text;outline:none;flex:1;padding:0;position:relative;overflow:auto}.F1KBNa_diffBody::-webkit-scrollbar,.F1KBNa_diffBody::-webkit-scrollbar-track,.F1KBNa_diffBody::-webkit-scrollbar-thumb{cursor:default}.F1KBNa_blockActions{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-markdown-code-block);box-shadow:var(--dsw-shadow-lv1);z-index:2;border-radius:10px;align-items:center;gap:9px;padding:5px;display:flex;position:absolute;right:8px}.F1KBNa_blockPosition{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;margin-top:1px;margin-left:7px;font-size:12px;line-height:16px}.F1KBNa_searchBar{z-index:3;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-markdown-code-block);box-shadow:var(--dsw-shadow-lv1);border-radius:10px;align-items:center;gap:4px;padding:4px;display:flex;position:absolute;top:8px;right:8px}.F1KBNa_searchInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);width:150px;color:var(--dsw-alias-label-primary);border-radius:6px;outline:none;padding:3px 8px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_searchInput:focus{border-color:var(--dsw-alias-state-business-primary)}.F1KBNa_searchCount{text-align:center;min-width:34px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:12px;line-height:16px}.F1KBNa_diffBody [data-diff-search=hit]{background-image:linear-gradient(#facc1529,#facc1529)}.F1KBNa_diffBody [data-diff-search=current]{background-image:linear-gradient(#facc1552,#facc1552)}.F1KBNa_blockFlash{z-index:1;box-sizing:border-box;border:2px solid var(--dsw-alias-state-business-primary);pointer-events:none;border-radius:4px;animation:1s ease-out forwards F1KBNa_diffFlash;position:absolute;left:0;right:0}@keyframes F1KBNa_diffFlash{0%{opacity:1}to{opacity:0}}.F1KBNa_overviewRuler{pointer-events:none;opacity:.5;width:4px;position:absolute;top:0;bottom:0;right:0}.F1KBNa_overviewMarker{border-radius:2px;width:100%;min-height:2px;position:absolute;right:0}.F1KBNa_markerDel{background-color:var(--dsw-alias-state-error-primary)}.F1KBNa_markerAdd{background-color:var(--dsw-alias-state-success-primary)}.F1KBNa_lines{border-spacing:0;width:max-content;min-width:100%;display:table}.F1KBNa_line{height:22px;line-height:22px;display:table-row}.F1KBNa_vSpacer{display:table-row}.F1KBNa_gutter{box-sizing:border-box;text-align:right;width:44px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;user-select:none;cursor:default;padding-right:10px;display:table-cell}.F1KBNa_code{white-space:pre;display:table-cell}.F1KBNa_context{color:var(--dsw-alias-label-primary)}.F1KBNa_del{background-color:color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent)}.F1KBNa_add{background-color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 10%, transparent)}.F1KBNa_statusBar{box-sizing:border-box;border-top:1px solid var(--dsw-alias-border-l2);height:34px;color:var(--dsw-alias-label-tertiary);font-family:var(--dsw-font-markdown-code-block);font-variant-numeric:tabular-nums;flex:none;align-items:center;padding:0 8px;font-size:12px;line-height:18px;display:flex}.F1KBNa_statusAction{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);white-space:nowrap;cursor:pointer;background:0 0;border-radius:8px;padding:3px 12px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_statusAction:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_langSelect{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;flex:none;align-items:center;gap:4px;padding:3px 12px;font-family:inherit;font-size:12px;line-height:18px;display:inline-flex}.F1KBNa_langSelect:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_langLabel{text-overflow:ellipsis;white-space:nowrap;max-width:140px;overflow:hidden}";
|
|
11625
11656
|
const tagId = "dsh-diff-approval/PendingPanel.module.css";
|
|
11626
11657
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
11627
11658
|
const tag = document.createElement("style");
|
|
@@ -11631,73 +11662,92 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11631
11662
|
document.head.appendChild(tag);
|
|
11632
11663
|
}
|
|
11633
11664
|
var PendingPanel_module_css_default = {
|
|
11634
|
-
"
|
|
11635
|
-
"
|
|
11636
|
-
"
|
|
11665
|
+
"expandExpanded": "F1KBNa_expandExpanded",
|
|
11666
|
+
"panel": "F1KBNa_panel",
|
|
11667
|
+
"fullscreenBackdrop": "F1KBNa_fullscreenBackdrop",
|
|
11668
|
+
"settingsPage": "F1KBNa_settingsPage",
|
|
11637
11669
|
"hint": "F1KBNa_hint",
|
|
11638
|
-
"
|
|
11639
|
-
"
|
|
11640
|
-
"
|
|
11641
|
-
"
|
|
11642
|
-
"
|
|
11643
|
-
"context": "F1KBNa_context",
|
|
11644
|
-
"kindTag": "F1KBNa_kindTag",
|
|
11645
|
-
"states": "F1KBNa_states",
|
|
11646
|
-
"resizeHandle": "F1KBNa_resizeHandle",
|
|
11647
|
-
"diffStats": "F1KBNa_diffStats",
|
|
11670
|
+
"row": "F1KBNa_row",
|
|
11671
|
+
"title": "F1KBNa_title",
|
|
11672
|
+
"blockActions": "F1KBNa_blockActions",
|
|
11673
|
+
"langLabel": "F1KBNa_langLabel",
|
|
11674
|
+
"detailEmpty": "F1KBNa_detailEmpty",
|
|
11648
11675
|
"del": "F1KBNa_del",
|
|
11676
|
+
"listScroll": "F1KBNa_listScroll",
|
|
11677
|
+
"close": "F1KBNa_close",
|
|
11678
|
+
"group": "F1KBNa_group",
|
|
11679
|
+
"diffActions": "F1KBNa_diffActions",
|
|
11680
|
+
"diffBodyWrap": "F1KBNa_diffBodyWrap",
|
|
11681
|
+
"states": "F1KBNa_states",
|
|
11649
11682
|
"searchInput": "F1KBNa_searchInput",
|
|
11650
|
-
"
|
|
11651
|
-
"
|
|
11652
|
-
"
|
|
11653
|
-
"
|
|
11654
|
-
"
|
|
11683
|
+
"settingsRowText": "F1KBNa_settingsRowText",
|
|
11684
|
+
"note": "F1KBNa_note",
|
|
11685
|
+
"addCount": "F1KBNa_addCount",
|
|
11686
|
+
"layer": "F1KBNa_layer",
|
|
11687
|
+
"diff": "F1KBNa_diff",
|
|
11688
|
+
"add": "F1KBNa_add",
|
|
11689
|
+
"overviewMarker": "F1KBNa_overviewMarker",
|
|
11690
|
+
"settingsRowDesc": "F1KBNa_settingsRowDesc",
|
|
11691
|
+
"actionQuietDisabled": "F1KBNa_actionQuietDisabled",
|
|
11692
|
+
"searchCount": "F1KBNa_searchCount",
|
|
11655
11693
|
"badgeCount": "F1KBNa_badgeCount",
|
|
11694
|
+
"context": "F1KBNa_context",
|
|
11695
|
+
"settingsSelectorChevron": "F1KBNa_settingsSelectorChevron",
|
|
11656
11696
|
"kindHint": "F1KBNa_kindHint",
|
|
11697
|
+
"footerButtons": "F1KBNa_footerButtons",
|
|
11698
|
+
"diffHeader": "F1KBNa_diffHeader",
|
|
11699
|
+
"resizeHandle": "F1KBNa_resizeHandle",
|
|
11700
|
+
"statusBar": "F1KBNa_statusBar",
|
|
11701
|
+
"rowPath": "F1KBNa_rowPath",
|
|
11702
|
+
"settingsSelector": "F1KBNa_settingsSelector",
|
|
11703
|
+
"importButton": "F1KBNa_importButton",
|
|
11704
|
+
"markerAdd": "F1KBNa_markerAdd",
|
|
11705
|
+
"header": "F1KBNa_header",
|
|
11706
|
+
"settingsRowTitle": "F1KBNa_settingsRowTitle",
|
|
11707
|
+
"emptyState": "F1KBNa_emptyState",
|
|
11657
11708
|
"rail": "F1KBNa_rail",
|
|
11658
|
-
"
|
|
11709
|
+
"diffFlash": "F1KBNa_diffFlash",
|
|
11659
11710
|
"action": "F1KBNa_action",
|
|
11660
|
-
"
|
|
11661
|
-
"
|
|
11662
|
-
"
|
|
11711
|
+
"detail": "F1KBNa_detail",
|
|
11712
|
+
"rowMeta": "F1KBNa_rowMeta",
|
|
11713
|
+
"actionError": "F1KBNa_actionError",
|
|
11714
|
+
"diffStats": "F1KBNa_diffStats",
|
|
11715
|
+
"flexSpacer": "F1KBNa_flexSpacer",
|
|
11716
|
+
"diffBody": "F1KBNa_diffBody",
|
|
11717
|
+
"statusAction": "F1KBNa_statusAction",
|
|
11663
11718
|
"readError": "F1KBNa_readError",
|
|
11664
|
-
"
|
|
11665
|
-
"
|
|
11719
|
+
"kindTag": "F1KBNa_kindTag",
|
|
11720
|
+
"delCount": "F1KBNa_delCount",
|
|
11721
|
+
"blockPosition": "F1KBNa_blockPosition",
|
|
11722
|
+
"overviewRuler": "F1KBNa_overviewRuler",
|
|
11723
|
+
"rowFailed": "F1KBNa_rowFailed",
|
|
11724
|
+
"headerActions": "F1KBNa_headerActions",
|
|
11666
11725
|
"divergedHint": "F1KBNa_divergedHint",
|
|
11667
|
-
"group": "F1KBNa_group",
|
|
11668
|
-
"diff": "F1KBNa_diff",
|
|
11669
11726
|
"code": "F1KBNa_code",
|
|
11670
|
-
"
|
|
11671
|
-
"
|
|
11727
|
+
"noteCentered": "F1KBNa_noteCentered",
|
|
11728
|
+
"expand": "F1KBNa_expand",
|
|
11729
|
+
"vSpacer": "F1KBNa_vSpacer",
|
|
11730
|
+
"importNote": "F1KBNa_importNote",
|
|
11731
|
+
"settingsRow": "F1KBNa_settingsRow",
|
|
11732
|
+
"split": "F1KBNa_split",
|
|
11672
11733
|
"missing": "F1KBNa_missing",
|
|
11673
|
-
"
|
|
11674
|
-
"
|
|
11734
|
+
"actionPrimary": "F1KBNa_actionPrimary",
|
|
11735
|
+
"blockFlash": "F1KBNa_blockFlash",
|
|
11736
|
+
"langSelect": "F1KBNa_langSelect",
|
|
11737
|
+
"badge": "F1KBNa_badge",
|
|
11738
|
+
"diffPath": "F1KBNa_diffPath",
|
|
11675
11739
|
"iconAction": "F1KBNa_iconAction",
|
|
11676
|
-
"
|
|
11677
|
-
"
|
|
11678
|
-
"
|
|
11679
|
-
"
|
|
11740
|
+
"markerDel": "F1KBNa_markerDel",
|
|
11741
|
+
"bulkActions": "F1KBNa_bulkActions",
|
|
11742
|
+
"gutter": "F1KBNa_gutter",
|
|
11743
|
+
"rowHead": "F1KBNa_rowHead",
|
|
11744
|
+
"searchBar": "F1KBNa_searchBar",
|
|
11745
|
+
"fileList": "F1KBNa_fileList",
|
|
11680
11746
|
"lines": "F1KBNa_lines",
|
|
11681
|
-
"panel": "F1KBNa_panel",
|
|
11682
|
-
"split": "F1KBNa_split",
|
|
11683
|
-
"badge": "F1KBNa_badge",
|
|
11684
|
-
"delCount": "F1KBNa_delCount",
|
|
11685
|
-
"overviewRuler": "F1KBNa_overviewRuler",
|
|
11686
|
-
"rowMeta": "F1KBNa_rowMeta",
|
|
11687
|
-
"blockActions": "F1KBNa_blockActions",
|
|
11688
11747
|
"rows": "F1KBNa_rows",
|
|
11689
|
-
"
|
|
11690
|
-
"
|
|
11691
|
-
"
|
|
11692
|
-
"statusBar": "F1KBNa_statusBar",
|
|
11693
|
-
"actionPrimary": "F1KBNa_actionPrimary",
|
|
11694
|
-
"rowHead": "F1KBNa_rowHead",
|
|
11695
|
-
"statusAction": "F1KBNa_statusAction",
|
|
11696
|
-
"diffPath": "F1KBNa_diffPath",
|
|
11697
|
-
"flexSpacer": "F1KBNa_flexSpacer",
|
|
11698
|
-
"blockPosition": "F1KBNa_blockPosition",
|
|
11699
|
-
"header": "F1KBNa_header",
|
|
11700
|
-
"overviewMarker": "F1KBNa_overviewMarker"
|
|
11748
|
+
"missingHint": "F1KBNa_missingHint",
|
|
11749
|
+
"line": "F1KBNa_line",
|
|
11750
|
+
"badgeLabel": "F1KBNa_badgeLabel"
|
|
11701
11751
|
};
|
|
11702
11752
|
//#endregion
|
|
11703
11753
|
//#region lib/types/client/PendingPanel.js
|
|
@@ -11731,23 +11781,49 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11731
11781
|
const MAX_LIST_WIDTH_PX = 560;
|
|
11732
11782
|
/** Fixed diff-row height in px; the virtual window and jump math are built on it. */
|
|
11733
11783
|
const ROW_HEIGHT_PX = 22;
|
|
11784
|
+
/** The overview ruler's width in px (mirrors `.overviewRuler`). The flash is
|
|
11785
|
+
* kept off it even when the scroller has no vertical scrollbar. */
|
|
11786
|
+
const OVERVIEW_RULER_WIDTH_PX = 4;
|
|
11734
11787
|
/** Rows rendered beyond the visible window in each direction. */
|
|
11735
11788
|
const OVERSCAN_ROWS = 8;
|
|
11736
11789
|
/** Height of the floating per-block Keep/Revert frame in px: 26px actions +
|
|
11737
11790
|
* 5px frame padding on each side + 1px border on each side, plus a little
|
|
11738
11791
|
* breathing room so the bottom padding never sits flush against it. */
|
|
11739
11792
|
const BLOCK_ACTIONS_FRAME_PX = 40;
|
|
11793
|
+
/** How long a fully-processed list stays open before the panel folds, so the
|
|
11794
|
+
* last action (a Keep-all/Revert-all especially) can still be undone with
|
|
11795
|
+
* Ctrl+Z. An undo that restores an entry cancels the pending close. */
|
|
11796
|
+
const EMPTY_CLOSE_GRACE_MS = 3e3;
|
|
11740
11797
|
/** The trailing file-name segment of a path, used for row display. */
|
|
11741
11798
|
function basenameOf(path) {
|
|
11742
11799
|
const index = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
|
|
11743
11800
|
return index < 0 ? path : path.slice(index + 1);
|
|
11744
11801
|
}
|
|
11802
|
+
/**
|
|
11803
|
+
* Open the DSH settings dialog and switch to this plugin's section. The
|
|
11804
|
+
* settings shell keeps its open state and the active section id as
|
|
11805
|
+
* component-local viewing state with no cross-plugin service, so the dialog
|
|
11806
|
+
* is opened by clicking the sidebar's settings trigger and then the nav cell
|
|
11807
|
+
* for this section. `element.click()` still fires React's delegated click
|
|
11808
|
+
* handlers, reaching the same state transitions a user gesture would.
|
|
11809
|
+
* @param sectionLabel - the nav label of this plugin's settings section.
|
|
11810
|
+
*/
|
|
11811
|
+
function openSettingsSection(sectionLabel) {
|
|
11812
|
+
const trigger = document.querySelector("button[aria-haspopup=\"dialog\"]");
|
|
11813
|
+
if (trigger === null) return;
|
|
11814
|
+
trigger.click();
|
|
11815
|
+
requestAnimationFrame(() => {
|
|
11816
|
+
Array.from(document.querySelectorAll("button")).find((button) => button.textContent?.trim() === sectionLabel)?.click();
|
|
11817
|
+
});
|
|
11818
|
+
}
|
|
11745
11819
|
/** The diff body's row class per line kind. */
|
|
11746
11820
|
const ROW_CLASS = {
|
|
11747
11821
|
context: PendingPanel_module_css_default.context,
|
|
11748
11822
|
del: PendingPanel_module_css_default.del,
|
|
11749
11823
|
add: PendingPanel_module_css_default.add
|
|
11750
11824
|
};
|
|
11825
|
+
/** Empty failure map reused as the snapshot's canonical absent value. */
|
|
11826
|
+
const EMPTY_FAILED_MAP = /* @__PURE__ */ new Map();
|
|
11751
11827
|
/**
|
|
11752
11828
|
* One rendered diff row, memoized so a poll or an unrelated state change
|
|
11753
11829
|
* does not re-render rows whose content, highlight, and focus are unchanged.
|
|
@@ -11909,7 +11985,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11909
11985
|
};
|
|
11910
11986
|
}
|
|
11911
11987
|
/** One row of the file list: the clickable head in the left pane. */
|
|
11912
|
-
function PendingFileRow({ file, selected, t, onSelect }) {
|
|
11988
|
+
function PendingFileRow({ file, selected, failedMessage, t, onSelect }) {
|
|
11913
11989
|
const stats = (0, react.useMemo)(() => computeWholeFileDiff(file.oldText, file.newText), [file.oldText, file.newText]);
|
|
11914
11990
|
return (0, react_jsx_runtime.jsx)("li", {
|
|
11915
11991
|
className: PendingPanel_module_css_default.row,
|
|
@@ -11938,6 +12014,11 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11938
12014
|
title: t("panel.missingHint"),
|
|
11939
12015
|
children: t("panel.missing")
|
|
11940
12016
|
}),
|
|
12017
|
+
failedMessage !== void 0 && (0, react_jsx_runtime.jsx)("span", {
|
|
12018
|
+
className: PendingPanel_module_css_default.rowFailed,
|
|
12019
|
+
title: failedMessage,
|
|
12020
|
+
children: t("row.failed")
|
|
12021
|
+
}),
|
|
11941
12022
|
(0, react_jsx_runtime.jsxs)("span", {
|
|
11942
12023
|
className: PendingPanel_module_css_default.rowMeta,
|
|
11943
12024
|
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
@@ -11954,7 +12035,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11954
12035
|
});
|
|
11955
12036
|
}
|
|
11956
12037
|
/** The selected file's diff, actions, jump controls, and copy toolbar. */
|
|
11957
|
-
function PendingDiff({ file, busy, workspacePath, jumpSignal, t, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen }) {
|
|
12038
|
+
function PendingDiff({ file, busy, workspacePath, jumpSignal, undoFlash, failedMessage, onPasteReference, t, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen }) {
|
|
11958
12039
|
const [langOverride, setLangOverride] = (0, react.useState)(void 0);
|
|
11959
12040
|
const [langMenuOpen, setLangMenuOpen] = (0, react.useState)(false);
|
|
11960
12041
|
const langMenuItems = (0, react.useMemo)(() => [{
|
|
@@ -12039,10 +12120,13 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12039
12120
|
const [searchQuery, setSearchQuery] = (0, react.useState)("");
|
|
12040
12121
|
const [searchIndex, setSearchIndex] = (0, react.useState)(0);
|
|
12041
12122
|
const searchInputRef = (0, react.useRef)(null);
|
|
12123
|
+
const [flashKey, setFlashKey] = (0, react.useState)(0);
|
|
12042
12124
|
(0, react.useEffect)(() => {
|
|
12043
12125
|
setFocus(0);
|
|
12044
12126
|
setScrollTop(0);
|
|
12045
12127
|
if (bodyRef.current !== null) bodyRef.current.scrollTop = 0;
|
|
12128
|
+
bodyRef.current?.focus();
|
|
12129
|
+
setFlashKey((key) => key + 1);
|
|
12046
12130
|
setHoveredBlock(void 0);
|
|
12047
12131
|
setSelection(void 0);
|
|
12048
12132
|
setLangOverride(void 0);
|
|
@@ -12052,6 +12136,12 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12052
12136
|
setSearchQuery("");
|
|
12053
12137
|
setSearchIndex(0);
|
|
12054
12138
|
}, [file.id]);
|
|
12139
|
+
(0, react.useEffect)(() => {
|
|
12140
|
+
if (undoFlash === 0) return;
|
|
12141
|
+
setFocus(0);
|
|
12142
|
+
setScrollTick((tick) => tick + 1);
|
|
12143
|
+
setFlashKey((key) => key + 1);
|
|
12144
|
+
}, [undoFlash]);
|
|
12055
12145
|
const blockRanges = (0, react.useMemo)(() => {
|
|
12056
12146
|
return model.blocks.map((block) => blockRangesOf(model.diff.rows, block));
|
|
12057
12147
|
}, [model]);
|
|
@@ -12086,7 +12176,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12086
12176
|
(0, react.useEffect)(() => {
|
|
12087
12177
|
setSearchIndex(0);
|
|
12088
12178
|
}, [searchQuery, file.id]);
|
|
12089
|
-
(0, react.
|
|
12179
|
+
(0, react.useLayoutEffect)(() => {
|
|
12090
12180
|
const row = currentSearchRow;
|
|
12091
12181
|
if (row === void 0) return;
|
|
12092
12182
|
const body = bodyRef.current;
|
|
@@ -12132,7 +12222,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12132
12222
|
observer?.disconnect();
|
|
12133
12223
|
};
|
|
12134
12224
|
}, [file.id]);
|
|
12135
|
-
(0, react.
|
|
12225
|
+
(0, react.useLayoutEffect)(() => {
|
|
12136
12226
|
if (rowCount === 0) return;
|
|
12137
12227
|
const block = model.blocks[focus];
|
|
12138
12228
|
if (block === void 0) return;
|
|
@@ -12161,6 +12251,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12161
12251
|
return 0;
|
|
12162
12252
|
});
|
|
12163
12253
|
setScrollTick((tick) => tick + 1);
|
|
12254
|
+
setFlashKey((key) => key + 1);
|
|
12164
12255
|
};
|
|
12165
12256
|
(0, react.useEffect)(() => {
|
|
12166
12257
|
if (jumpSignal === 0) return;
|
|
@@ -12190,10 +12281,15 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12190
12281
|
if (selectionReference === void 0) return;
|
|
12191
12282
|
if (!await (0, _deepseek_ai_dsh_client_ui_primitives.writeClipboard)(selectionReference)) return;
|
|
12192
12283
|
setCopied(true);
|
|
12284
|
+
if (pasteOnCopyEnabled()) onPasteReference(file.sessionId, selectionReference);
|
|
12193
12285
|
window.setTimeout(() => {
|
|
12194
12286
|
setCopied(false);
|
|
12195
12287
|
}, 1500);
|
|
12196
|
-
}, [
|
|
12288
|
+
}, [
|
|
12289
|
+
file.sessionId,
|
|
12290
|
+
onPasteReference,
|
|
12291
|
+
selectionReference
|
|
12292
|
+
]);
|
|
12197
12293
|
(0, react.useEffect)(() => {
|
|
12198
12294
|
const onKeyDown = (event) => {
|
|
12199
12295
|
if (!(event.ctrlKey || event.metaKey) || event.altKey || event.shiftKey) return;
|
|
@@ -12202,9 +12298,9 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12202
12298
|
event.preventDefault();
|
|
12203
12299
|
copySelection();
|
|
12204
12300
|
};
|
|
12205
|
-
|
|
12301
|
+
window.addEventListener("keydown", onKeyDown, true);
|
|
12206
12302
|
return () => {
|
|
12207
|
-
|
|
12303
|
+
window.removeEventListener("keydown", onKeyDown, true);
|
|
12208
12304
|
};
|
|
12209
12305
|
}, [copySelection]);
|
|
12210
12306
|
(0, react.useEffect)(() => {
|
|
@@ -12221,8 +12317,31 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12221
12317
|
window.removeEventListener("keydown", onKeyDown, true);
|
|
12222
12318
|
};
|
|
12223
12319
|
}, []);
|
|
12320
|
+
const jumpRef = (0, react.useRef)(jump);
|
|
12321
|
+
jumpRef.current = jump;
|
|
12322
|
+
(0, react.useEffect)(() => {
|
|
12323
|
+
const onKeyDown = (event) => {
|
|
12324
|
+
if (!(event.ctrlKey || event.metaKey) || event.altKey || event.shiftKey) return;
|
|
12325
|
+
const key = event.key.toLowerCase();
|
|
12326
|
+
if (key !== "arrowup" && key !== "arrowdown") return;
|
|
12327
|
+
const target = event.target;
|
|
12328
|
+
if (target instanceof Element && target.closest("input, textarea, [contenteditable=\"true\"]") !== null) return;
|
|
12329
|
+
event.preventDefault();
|
|
12330
|
+
jumpRef.current(key === "arrowup" ? -1 : 1);
|
|
12331
|
+
};
|
|
12332
|
+
window.addEventListener("keydown", onKeyDown, true);
|
|
12333
|
+
return () => {
|
|
12334
|
+
window.removeEventListener("keydown", onKeyDown, true);
|
|
12335
|
+
};
|
|
12336
|
+
}, []);
|
|
12224
12337
|
const focusedBlock = model.blocks.length > 0 ? model.blocks[focus] : void 0;
|
|
12225
12338
|
const inFocusedBlock = (index) => focusedBlock !== void 0 && index >= focusedBlock.start && index <= focusedBlock.end;
|
|
12339
|
+
const flashWidth = (() => {
|
|
12340
|
+
const scroller = bodyRef.current;
|
|
12341
|
+
if (scroller === null) return 0;
|
|
12342
|
+
const scrollbarWidth = scroller.offsetWidth - scroller.clientWidth;
|
|
12343
|
+
return Math.max(0, scroller.clientWidth - (scrollbarWidth > 0 ? 0 : OVERVIEW_RULER_WIDTH_PX));
|
|
12344
|
+
})();
|
|
12226
12345
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
12227
12346
|
className: PendingPanel_module_css_default.diff,
|
|
12228
12347
|
"data-diff-approval-diff": true,
|
|
@@ -12327,26 +12446,31 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12327
12446
|
(0, react_jsx_runtime.jsx)("span", { className: PendingPanel_module_css_default.flexSpacer }),
|
|
12328
12447
|
(0, react_jsx_runtime.jsx)("button", {
|
|
12329
12448
|
type: "button",
|
|
12330
|
-
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.actionPrimary}`,
|
|
12449
|
+
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.actionPrimary} ${PendingPanel_module_css_default.actionQuietDisabled}`,
|
|
12331
12450
|
"data-diff-keep": true,
|
|
12332
12451
|
disabled: busy,
|
|
12333
12452
|
onClick: () => {
|
|
12334
12453
|
onKeep(file.sessionId, file.id);
|
|
12335
12454
|
},
|
|
12336
|
-
children:
|
|
12455
|
+
children: t("action.keep")
|
|
12337
12456
|
}),
|
|
12338
12457
|
(0, react_jsx_runtime.jsx)("button", {
|
|
12339
12458
|
type: "button",
|
|
12340
|
-
className: PendingPanel_module_css_default.action
|
|
12459
|
+
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.actionQuietDisabled}`,
|
|
12341
12460
|
"data-diff-revert": true,
|
|
12342
12461
|
disabled: busy,
|
|
12343
12462
|
onClick: () => {
|
|
12344
12463
|
onRevert(file.sessionId, file.id);
|
|
12345
12464
|
},
|
|
12346
|
-
children:
|
|
12465
|
+
children: t("action.revert")
|
|
12347
12466
|
})
|
|
12348
12467
|
]
|
|
12349
12468
|
}),
|
|
12469
|
+
failedMessage !== void 0 && (0, react_jsx_runtime.jsx)("p", {
|
|
12470
|
+
className: PendingPanel_module_css_default.actionError,
|
|
12471
|
+
"data-diff-action-error": true,
|
|
12472
|
+
children: failedMessage
|
|
12473
|
+
}),
|
|
12350
12474
|
file.missing && (0, react_jsx_runtime.jsx)("p", {
|
|
12351
12475
|
className: PendingPanel_module_css_default.missingHint,
|
|
12352
12476
|
children: t("panel.missingHint")
|
|
@@ -12357,6 +12481,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12357
12481
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
12358
12482
|
className: PendingPanel_module_css_default.diffBody,
|
|
12359
12483
|
ref: bodyRef,
|
|
12484
|
+
tabIndex: 0,
|
|
12360
12485
|
onScroll,
|
|
12361
12486
|
onMouseLeave: () => {
|
|
12362
12487
|
setHoveredBlock(void 0);
|
|
@@ -12430,6 +12555,15 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12430
12555
|
]
|
|
12431
12556
|
})]
|
|
12432
12557
|
}),
|
|
12558
|
+
focusedBlock !== void 0 && flashKey > 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
12559
|
+
className: PendingPanel_module_css_default.blockFlash,
|
|
12560
|
+
"data-diff-block-flash": true,
|
|
12561
|
+
style: {
|
|
12562
|
+
top: focusedBlock.start * ROW_HEIGHT_PX - scrollTop,
|
|
12563
|
+
height: Math.min((focusedBlock.end - focusedBlock.start + 1) * ROW_HEIGHT_PX, viewportHeight > 0 ? viewportHeight : Number.POSITIVE_INFINITY),
|
|
12564
|
+
width: flashWidth
|
|
12565
|
+
}
|
|
12566
|
+
}, flashKey),
|
|
12433
12567
|
searchOpen && (0, react_jsx_runtime.jsxs)("div", {
|
|
12434
12568
|
className: PendingPanel_module_css_default.searchBar,
|
|
12435
12569
|
"data-diff-searchbar": true,
|
|
@@ -12563,14 +12697,34 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12563
12697
|
});
|
|
12564
12698
|
}
|
|
12565
12699
|
/** Render the pending-edit review panel and its unified footer action. */
|
|
12566
|
-
function PendingPanel({ wide, useSessions, usePending, onRefresh, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen, t }) {
|
|
12700
|
+
function PendingPanel({ wide, useSessions, usePending, onRefresh, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen, onPasteReference, onUndo, onRedo, onImportVcs, t }) {
|
|
12567
12701
|
const current = useSessions((state) => state.current);
|
|
12702
|
+
const currentBlank = useSessions((state) => {
|
|
12703
|
+
const id = state.current;
|
|
12704
|
+
return id === void 0 ? false : state.byId[id]?.blank ?? false;
|
|
12705
|
+
});
|
|
12706
|
+
const noSession = current === void 0 || currentBlank;
|
|
12568
12707
|
const snapshot = usePending((snapshot) => snapshot);
|
|
12569
12708
|
const [open, setOpen] = (0, react.useState)(false);
|
|
12570
12709
|
const [selected, setSelected] = (0, react.useState)("");
|
|
12571
12710
|
/** Bumped when the already-open file is clicked again, to jump to the next
|
|
12572
12711
|
* diff block in the open file's detail pane. */
|
|
12573
12712
|
const [jumpSignal, setJumpSignal] = (0, react.useState)(0);
|
|
12713
|
+
/** Bumped when an undo/redo affected the already-open file, so its detail
|
|
12714
|
+
* pane re-selects the undone diff (flash). */
|
|
12715
|
+
const [undoFlash, setUndoFlash] = (0, react.useState)(0);
|
|
12716
|
+
/** Which bulk decision (keep-all / revert-all) is running; null when idle. */
|
|
12717
|
+
const [bulkBusy, setBulkBusy] = (0, react.useState)(null);
|
|
12718
|
+
/** True while a workspace-changes import is running. */
|
|
12719
|
+
const [importBusy, setImportBusy] = (0, react.useState)(false);
|
|
12720
|
+
/** Feedback under the empty note after an import (no VCS, or a failure). */
|
|
12721
|
+
const [importNote, setImportNote] = (0, react.useState)(void 0);
|
|
12722
|
+
/** Whether the last import note is a failure (drives the alert role). */
|
|
12723
|
+
const [importFailed, setImportFailed] = (0, react.useState)(false);
|
|
12724
|
+
/** A transient banner for an import that found nothing to bring in. */
|
|
12725
|
+
const [importToast, setImportToast] = (0, react.useState)(null);
|
|
12726
|
+
/** A transient banner for a keep/revert failure. */
|
|
12727
|
+
const [actionToast, setActionToast] = (0, react.useState)(null);
|
|
12574
12728
|
/** Pending count captured at open time; auto-close needs a list that emptied. */
|
|
12575
12729
|
const [openedCount, setOpenedCount] = (0, react.useState)(0);
|
|
12576
12730
|
/** Bottom offset tracking the chat composer's top edge so the input stays visible. */
|
|
@@ -12633,6 +12787,22 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12633
12787
|
};
|
|
12634
12788
|
}, [open]);
|
|
12635
12789
|
const files = snapshot.files.filter((file) => file.sessionId === current);
|
|
12790
|
+
/** Per-file keep/revert failures, surfaced inline on the row and detail. */
|
|
12791
|
+
const failed = snapshot.failed ?? EMPTY_FAILED_MAP;
|
|
12792
|
+
const failedInitialized = (0, react.useRef)(false);
|
|
12793
|
+
const failedRef = (0, react.useRef)(void 0);
|
|
12794
|
+
(0, react.useEffect)(() => {
|
|
12795
|
+
const current = snapshot.failed;
|
|
12796
|
+
if (!failedInitialized.current) {
|
|
12797
|
+
failedInitialized.current = true;
|
|
12798
|
+
failedRef.current = current;
|
|
12799
|
+
return;
|
|
12800
|
+
}
|
|
12801
|
+
const previous = failedRef.current;
|
|
12802
|
+
const fresh = [...(current ?? EMPTY_FAILED_MAP).entries()].filter(([id]) => previous === void 0 || !previous.has(id));
|
|
12803
|
+
if (fresh.length > 0) setActionToast(fresh[0][1]);
|
|
12804
|
+
failedRef.current = current;
|
|
12805
|
+
}, [snapshot.failed]);
|
|
12636
12806
|
(0, react.useEffect)(() => {
|
|
12637
12807
|
if (!open) return;
|
|
12638
12808
|
if (selected !== "" && files.some((file) => file.id === selected)) return;
|
|
@@ -12645,10 +12815,15 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12645
12815
|
selected
|
|
12646
12816
|
]);
|
|
12647
12817
|
(0, react.useEffect)(() => {
|
|
12648
|
-
if (open
|
|
12818
|
+
if (!open || openedCount === 0) return;
|
|
12819
|
+
if (!(snapshot.read && snapshot.error === void 0 && files.length === 0)) return;
|
|
12820
|
+
const timer = window.setTimeout(() => {
|
|
12649
12821
|
setOpenedCount(0);
|
|
12650
12822
|
setOpen(false);
|
|
12651
|
-
}
|
|
12823
|
+
}, EMPTY_CLOSE_GRACE_MS);
|
|
12824
|
+
return () => {
|
|
12825
|
+
window.clearTimeout(timer);
|
|
12826
|
+
};
|
|
12652
12827
|
}, [
|
|
12653
12828
|
open,
|
|
12654
12829
|
openedCount,
|
|
@@ -12656,13 +12831,45 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12656
12831
|
snapshot.error,
|
|
12657
12832
|
files.length
|
|
12658
12833
|
]);
|
|
12834
|
+
const runImportVcs = async () => {
|
|
12835
|
+
if (current === void 0 || importBusy) return;
|
|
12836
|
+
setImportBusy(true);
|
|
12837
|
+
setImportNote(void 0);
|
|
12838
|
+
setImportFailed(false);
|
|
12839
|
+
setImportToast(null);
|
|
12840
|
+
try {
|
|
12841
|
+
const value = await onImportVcs(current, includeUntrackedEnabled());
|
|
12842
|
+
await onRefresh(current);
|
|
12843
|
+
if (!value.detected) setImportNote(t("panel.importNoVcs"));
|
|
12844
|
+
else if (value.imported === 0) setImportToast(t("panel.importNone"));
|
|
12845
|
+
} catch (error) {
|
|
12846
|
+
setImportFailed(true);
|
|
12847
|
+
setImportNote(t("panel.importFailed", { message: error instanceof Error ? error.message : String(error) }));
|
|
12848
|
+
} finally {
|
|
12849
|
+
setImportBusy(false);
|
|
12850
|
+
}
|
|
12851
|
+
};
|
|
12659
12852
|
const toggleOpen = () => {
|
|
12660
12853
|
if (!open) setOpenedCount(files.length);
|
|
12661
12854
|
setOpen((value) => !value);
|
|
12662
12855
|
};
|
|
12856
|
+
(0, react.useEffect)(() => {
|
|
12857
|
+
if (noSession) setOpen(false);
|
|
12858
|
+
}, [noSession]);
|
|
12859
|
+
/** Run the same decision over every current-session file, sequentially. */
|
|
12860
|
+
const runBulk = async (kind) => {
|
|
12861
|
+
setBulkBusy(kind);
|
|
12862
|
+
try {
|
|
12863
|
+
for (const file of files) if (kind === "keep") await onKeep(file.sessionId, file.id);
|
|
12864
|
+
else await onRevert(file.sessionId, file.id);
|
|
12865
|
+
} finally {
|
|
12866
|
+
setBulkBusy(null);
|
|
12867
|
+
}
|
|
12868
|
+
};
|
|
12663
12869
|
const renderEntry = (entry) => (0, react_jsx_runtime.jsx)(PendingFileRow, {
|
|
12664
12870
|
file: entry,
|
|
12665
12871
|
selected: selected === entry.id,
|
|
12872
|
+
failedMessage: failed.get(entry.id),
|
|
12666
12873
|
t,
|
|
12667
12874
|
onSelect: (id) => {
|
|
12668
12875
|
if (id === selected) setJumpSignal((signal) => signal + 1);
|
|
@@ -12670,6 +12877,42 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12670
12877
|
}
|
|
12671
12878
|
}, entry.id);
|
|
12672
12879
|
const selectedFile = files.find((file) => file.id === selected);
|
|
12880
|
+
const handleUndo = async (sessionId) => {
|
|
12881
|
+
const id = await onUndo(sessionId);
|
|
12882
|
+
if (id === void 0) return;
|
|
12883
|
+
if (id === selected) setUndoFlash((signal) => signal + 1);
|
|
12884
|
+
else setSelected(id);
|
|
12885
|
+
};
|
|
12886
|
+
const handleRedo = async (sessionId) => {
|
|
12887
|
+
const id = await onRedo(sessionId);
|
|
12888
|
+
if (id === void 0) return;
|
|
12889
|
+
if (id === selected) setUndoFlash((signal) => signal + 1);
|
|
12890
|
+
else setSelected(id);
|
|
12891
|
+
};
|
|
12892
|
+
(0, react.useEffect)(() => {
|
|
12893
|
+
if (!open || current === void 0) return;
|
|
12894
|
+
const onKeyDown = (event) => {
|
|
12895
|
+
if (!(event.ctrlKey || event.metaKey) || event.altKey) return;
|
|
12896
|
+
const key = event.key.toLowerCase();
|
|
12897
|
+
if (key !== "z" && key !== "y") return;
|
|
12898
|
+
const target = event.target;
|
|
12899
|
+
if (target instanceof Element && target.closest("input, textarea, [contenteditable=\"true\"]") !== null) return;
|
|
12900
|
+
event.preventDefault();
|
|
12901
|
+
if (key === "z") {
|
|
12902
|
+
if (event.shiftKey) handleRedo(current);
|
|
12903
|
+
else handleUndo(current);
|
|
12904
|
+
} else handleRedo(current);
|
|
12905
|
+
};
|
|
12906
|
+
window.addEventListener("keydown", onKeyDown, true);
|
|
12907
|
+
return () => {
|
|
12908
|
+
window.removeEventListener("keydown", onKeyDown, true);
|
|
12909
|
+
};
|
|
12910
|
+
}, [
|
|
12911
|
+
open,
|
|
12912
|
+
current,
|
|
12913
|
+
handleUndo,
|
|
12914
|
+
handleRedo
|
|
12915
|
+
]);
|
|
12673
12916
|
/** Drag the list/detail divider; width follows the pointer within its bounds. */
|
|
12674
12917
|
const startResize = (event) => {
|
|
12675
12918
|
if (event.button !== 0) return;
|
|
@@ -12698,127 +12941,316 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12698
12941
|
};
|
|
12699
12942
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
12700
12943
|
className: wide ? PendingPanel_module_css_default.layer : `${PendingPanel_module_css_default.layer} ${PendingPanel_module_css_default.rail}`,
|
|
12701
|
-
children: [
|
|
12702
|
-
|
|
12703
|
-
|
|
12704
|
-
|
|
12705
|
-
|
|
12706
|
-
|
|
12707
|
-
|
|
12708
|
-
|
|
12709
|
-
|
|
12710
|
-
|
|
12711
|
-
|
|
12712
|
-
|
|
12713
|
-
|
|
12714
|
-
|
|
12715
|
-
|
|
12716
|
-
|
|
12717
|
-
|
|
12718
|
-
|
|
12719
|
-
|
|
12720
|
-
|
|
12721
|
-
|
|
12722
|
-
|
|
12723
|
-
|
|
12724
|
-
|
|
12725
|
-
|
|
12944
|
+
children: [
|
|
12945
|
+
importToast !== null && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Toast, {
|
|
12946
|
+
text: importToast,
|
|
12947
|
+
onDone: () => {
|
|
12948
|
+
setImportToast(null);
|
|
12949
|
+
}
|
|
12950
|
+
}),
|
|
12951
|
+
actionToast !== null && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Toast, {
|
|
12952
|
+
text: actionToast,
|
|
12953
|
+
onDone: () => {
|
|
12954
|
+
setActionToast(null);
|
|
12955
|
+
}
|
|
12956
|
+
}),
|
|
12957
|
+
open && expanded && (0, react_jsx_runtime.jsx)("div", {
|
|
12958
|
+
className: PendingPanel_module_css_default.fullscreenBackdrop,
|
|
12959
|
+
"data-diff-fullscreen-backdrop": true
|
|
12960
|
+
}),
|
|
12961
|
+
open && (0, react_jsx_runtime.jsxs)("section", {
|
|
12962
|
+
className: PendingPanel_module_css_default.panel,
|
|
12963
|
+
style: { bottom: expanded ? PANEL_INSET_PX : bottomPx },
|
|
12964
|
+
"data-diff-approval-panel": true,
|
|
12965
|
+
"aria-label": t("panel.title"),
|
|
12966
|
+
children: [(0, react_jsx_runtime.jsxs)("header", {
|
|
12967
|
+
className: PendingPanel_module_css_default.header,
|
|
12968
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
12969
|
+
className: PendingPanel_module_css_default.title,
|
|
12970
|
+
children: t("panel.title")
|
|
12971
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
12972
|
+
className: PendingPanel_module_css_default.headerActions,
|
|
12973
|
+
children: [
|
|
12974
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
12975
|
+
label: t("action.settings"),
|
|
12976
|
+
side: "bottom",
|
|
12977
|
+
delayMs: 500,
|
|
12978
|
+
children: (0, react_jsx_runtime.jsx)("button", {
|
|
12979
|
+
type: "button",
|
|
12980
|
+
className: PendingPanel_module_css_default.expand,
|
|
12981
|
+
"data-diff-approval-settings": true,
|
|
12982
|
+
"aria-label": t("action.settings"),
|
|
12983
|
+
onClick: () => {
|
|
12984
|
+
setOpen(false);
|
|
12985
|
+
openSettingsSection(t("settings.tabLabel"));
|
|
12986
|
+
},
|
|
12987
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSettingsOutline16, { size: 14 })
|
|
12988
|
+
})
|
|
12989
|
+
}),
|
|
12990
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
12991
|
+
label: t(expanded ? "action.exitFullscreen" : "action.expand"),
|
|
12992
|
+
side: "bottom",
|
|
12993
|
+
delayMs: 500,
|
|
12994
|
+
children: (0, react_jsx_runtime.jsx)("button", {
|
|
12995
|
+
type: "button",
|
|
12996
|
+
className: expanded ? `${PendingPanel_module_css_default.expand} ${PendingPanel_module_css_default.expandExpanded}` : PendingPanel_module_css_default.expand,
|
|
12997
|
+
"data-diff-approval-expand": true,
|
|
12998
|
+
"aria-label": t(expanded ? "action.exitFullscreen" : "action.expand"),
|
|
12999
|
+
onClick: () => {
|
|
13000
|
+
setExpanded((value) => !value);
|
|
13001
|
+
},
|
|
13002
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFullscreenOutline16, { size: 14 })
|
|
13003
|
+
})
|
|
13004
|
+
}),
|
|
13005
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
13006
|
+
label: t("action.close"),
|
|
13007
|
+
side: "bottom",
|
|
13008
|
+
delayMs: 500,
|
|
13009
|
+
children: (0, react_jsx_runtime.jsx)("button", {
|
|
13010
|
+
type: "button",
|
|
13011
|
+
className: PendingPanel_module_css_default.close,
|
|
13012
|
+
"data-diff-approval-close": true,
|
|
13013
|
+
"aria-label": t("action.close"),
|
|
13014
|
+
onClick: () => {
|
|
13015
|
+
setOpen(false);
|
|
13016
|
+
},
|
|
13017
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCloseOutline16, { size: 14 })
|
|
13018
|
+
})
|
|
13019
|
+
})
|
|
13020
|
+
]
|
|
13021
|
+
})]
|
|
13022
|
+
}), snapshot.error !== void 0 || !snapshot.read || files.length === 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
13023
|
+
className: PendingPanel_module_css_default.states,
|
|
13024
|
+
children: [
|
|
13025
|
+
snapshot.error !== void 0 && (0, react_jsx_runtime.jsx)("p", {
|
|
13026
|
+
className: PendingPanel_module_css_default.readError,
|
|
13027
|
+
role: "alert",
|
|
13028
|
+
children: t("panel.readFailed", { message: snapshot.error })
|
|
13029
|
+
}),
|
|
13030
|
+
!snapshot.read && snapshot.error === void 0 && (0, react_jsx_runtime.jsx)("p", {
|
|
13031
|
+
className: PendingPanel_module_css_default.note,
|
|
13032
|
+
children: t("panel.loading")
|
|
13033
|
+
}),
|
|
13034
|
+
snapshot.read && snapshot.error === void 0 && files.length === 0 && (0, react_jsx_runtime.jsxs)("div", {
|
|
13035
|
+
className: PendingPanel_module_css_default.emptyState,
|
|
13036
|
+
children: [
|
|
13037
|
+
(0, react_jsx_runtime.jsx)("p", {
|
|
13038
|
+
className: `${PendingPanel_module_css_default.note} ${PendingPanel_module_css_default.noteCentered}`,
|
|
13039
|
+
children: t("panel.empty")
|
|
13040
|
+
}),
|
|
13041
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
13042
|
+
type: "button",
|
|
13043
|
+
className: PendingPanel_module_css_default.importButton,
|
|
13044
|
+
"data-diff-import-vcs": true,
|
|
13045
|
+
disabled: importBusy,
|
|
13046
|
+
onClick: () => {
|
|
13047
|
+
runImportVcs();
|
|
13048
|
+
},
|
|
13049
|
+
children: importBusy ? t("action.importVcsBusy") : t("action.importVcs")
|
|
13050
|
+
}),
|
|
13051
|
+
importNote !== void 0 && (0, react_jsx_runtime.jsx)("p", {
|
|
13052
|
+
className: PendingPanel_module_css_default.importNote,
|
|
13053
|
+
role: importFailed ? "alert" : void 0,
|
|
13054
|
+
children: importNote
|
|
13055
|
+
})
|
|
13056
|
+
]
|
|
12726
13057
|
})
|
|
12727
|
-
|
|
12728
|
-
|
|
12729
|
-
|
|
12730
|
-
|
|
12731
|
-
|
|
12732
|
-
|
|
12733
|
-
|
|
12734
|
-
"data-diff-approval-
|
|
12735
|
-
|
|
12736
|
-
|
|
12737
|
-
|
|
12738
|
-
|
|
12739
|
-
|
|
13058
|
+
]
|
|
13059
|
+
}) : (0, react_jsx_runtime.jsxs)("div", {
|
|
13060
|
+
className: PendingPanel_module_css_default.split,
|
|
13061
|
+
children: [
|
|
13062
|
+
(0, react_jsx_runtime.jsxs)("nav", {
|
|
13063
|
+
className: PendingPanel_module_css_default.fileList,
|
|
13064
|
+
style: { width: listWidth },
|
|
13065
|
+
"data-diff-approval-file-list": true,
|
|
13066
|
+
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
13067
|
+
className: PendingPanel_module_css_default.listScroll,
|
|
13068
|
+
children: files.length > 0 && (0, react_jsx_runtime.jsxs)("section", { children: [(0, react_jsx_runtime.jsx)("h3", {
|
|
13069
|
+
className: PendingPanel_module_css_default.group,
|
|
13070
|
+
children: t("panel.group.current")
|
|
13071
|
+
}), (0, react_jsx_runtime.jsx)("ul", {
|
|
13072
|
+
className: PendingPanel_module_css_default.rows,
|
|
13073
|
+
children: files.map(renderEntry)
|
|
13074
|
+
})] })
|
|
13075
|
+
}), files.length > 0 && (0, react_jsx_runtime.jsxs)("div", {
|
|
13076
|
+
className: PendingPanel_module_css_default.bulkActions,
|
|
13077
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
13078
|
+
type: "button",
|
|
13079
|
+
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.actionPrimary}`,
|
|
13080
|
+
"data-diff-keep-all": true,
|
|
13081
|
+
disabled: bulkBusy !== null,
|
|
13082
|
+
onClick: () => {
|
|
13083
|
+
runBulk("keep");
|
|
13084
|
+
},
|
|
13085
|
+
children: bulkBusy === "keep" ? t("action.busy") : t("action.keepAll")
|
|
13086
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
13087
|
+
type: "button",
|
|
13088
|
+
className: PendingPanel_module_css_default.action,
|
|
13089
|
+
"data-diff-revert-all": true,
|
|
13090
|
+
disabled: bulkBusy !== null,
|
|
13091
|
+
onClick: () => {
|
|
13092
|
+
runBulk("revert");
|
|
13093
|
+
},
|
|
13094
|
+
children: bulkBusy === "revert" ? t("action.busy") : t("action.revertAll")
|
|
13095
|
+
})]
|
|
13096
|
+
})]
|
|
13097
|
+
}),
|
|
13098
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
13099
|
+
className: PendingPanel_module_css_default.resizeHandle,
|
|
13100
|
+
"data-diff-resize": true,
|
|
13101
|
+
onMouseDown: startResize
|
|
13102
|
+
}),
|
|
13103
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
13104
|
+
className: PendingPanel_module_css_default.detail,
|
|
13105
|
+
children: selectedFile === void 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
13106
|
+
className: PendingPanel_module_css_default.detailEmpty,
|
|
13107
|
+
children: t("panel.selectHint")
|
|
13108
|
+
}) : (0, react_jsx_runtime.jsx)(PendingDiff, {
|
|
13109
|
+
file: selectedFile,
|
|
13110
|
+
busy: snapshot.busy.has(selectedFile.id),
|
|
13111
|
+
workspacePath: snapshot.workspacePath,
|
|
13112
|
+
jumpSignal,
|
|
13113
|
+
undoFlash,
|
|
13114
|
+
failedMessage: failed.get(selectedFile.id),
|
|
13115
|
+
onPasteReference,
|
|
13116
|
+
t,
|
|
13117
|
+
onKeep,
|
|
13118
|
+
onRevert,
|
|
13119
|
+
onBlockKeep,
|
|
13120
|
+
onBlockRevert,
|
|
13121
|
+
onOpen
|
|
13122
|
+
})
|
|
12740
13123
|
})
|
|
12741
|
-
|
|
13124
|
+
]
|
|
12742
13125
|
})]
|
|
12743
|
-
}),
|
|
12744
|
-
|
|
12745
|
-
|
|
12746
|
-
|
|
12747
|
-
|
|
12748
|
-
|
|
12749
|
-
|
|
12750
|
-
|
|
12751
|
-
|
|
12752
|
-
|
|
12753
|
-
|
|
12754
|
-
|
|
12755
|
-
|
|
12756
|
-
|
|
12757
|
-
|
|
12758
|
-
|
|
12759
|
-
|
|
12760
|
-
|
|
12761
|
-
|
|
12762
|
-
|
|
12763
|
-
|
|
12764
|
-
className: PendingPanel_module_css_default.fileList,
|
|
12765
|
-
style: { width: listWidth },
|
|
12766
|
-
"data-diff-approval-file-list": true,
|
|
12767
|
-
children: files.length > 0 && (0, react_jsx_runtime.jsxs)("section", { children: [(0, react_jsx_runtime.jsx)("h3", {
|
|
12768
|
-
className: PendingPanel_module_css_default.group,
|
|
12769
|
-
children: t("panel.group.current")
|
|
12770
|
-
}), (0, react_jsx_runtime.jsx)("ul", {
|
|
12771
|
-
className: PendingPanel_module_css_default.rows,
|
|
12772
|
-
children: files.map(renderEntry)
|
|
12773
|
-
})] })
|
|
12774
|
-
}),
|
|
12775
|
-
(0, react_jsx_runtime.jsx)("div", {
|
|
12776
|
-
className: PendingPanel_module_css_default.resizeHandle,
|
|
12777
|
-
"data-diff-resize": true,
|
|
12778
|
-
onMouseDown: startResize
|
|
12779
|
-
}),
|
|
12780
|
-
(0, react_jsx_runtime.jsx)("div", {
|
|
12781
|
-
className: PendingPanel_module_css_default.detail,
|
|
12782
|
-
children: selectedFile === void 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
12783
|
-
className: PendingPanel_module_css_default.detailEmpty,
|
|
12784
|
-
children: t("panel.selectHint")
|
|
12785
|
-
}) : (0, react_jsx_runtime.jsx)(PendingDiff, {
|
|
12786
|
-
file: selectedFile,
|
|
12787
|
-
busy: snapshot.busy.has(selectedFile.id),
|
|
12788
|
-
workspacePath: snapshot.workspacePath,
|
|
12789
|
-
jumpSignal,
|
|
12790
|
-
t,
|
|
12791
|
-
onKeep,
|
|
12792
|
-
onRevert,
|
|
12793
|
-
onBlockKeep,
|
|
12794
|
-
onBlockRevert,
|
|
12795
|
-
onOpen
|
|
13126
|
+
}),
|
|
13127
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
13128
|
+
className: PendingPanel_module_css_default.footerButtons,
|
|
13129
|
+
children: (0, react_jsx_runtime.jsxs)("button", {
|
|
13130
|
+
type: "button",
|
|
13131
|
+
className: noSession ? `${PendingPanel_module_css_default.badge} ${PendingPanel_module_css_default.badgeDisabled}` : PendingPanel_module_css_default.badge,
|
|
13132
|
+
"data-diff-approval-badge": files.length,
|
|
13133
|
+
"data-active": open ? "" : void 0,
|
|
13134
|
+
"aria-label": t("panel.aria"),
|
|
13135
|
+
"aria-expanded": open,
|
|
13136
|
+
disabled: noSession,
|
|
13137
|
+
onClick: toggleOpen,
|
|
13138
|
+
children: [
|
|
13139
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconListPenOutline16, { size: wide ? 16 : 18 }),
|
|
13140
|
+
wide && (0, react_jsx_runtime.jsx)("span", {
|
|
13141
|
+
className: PendingPanel_module_css_default.badgeLabel,
|
|
13142
|
+
children: t("panel.aria")
|
|
13143
|
+
}),
|
|
13144
|
+
(wide || files.length > 0) && (0, react_jsx_runtime.jsx)("span", {
|
|
13145
|
+
className: PendingPanel_module_css_default.badgeCount,
|
|
13146
|
+
children: files.length
|
|
12796
13147
|
})
|
|
12797
|
-
|
|
12798
|
-
|
|
12799
|
-
})]
|
|
12800
|
-
}), (0, react_jsx_runtime.jsx)("div", {
|
|
12801
|
-
className: PendingPanel_module_css_default.footerButtons,
|
|
12802
|
-
children: (0, react_jsx_runtime.jsxs)("button", {
|
|
12803
|
-
type: "button",
|
|
12804
|
-
className: PendingPanel_module_css_default.badge,
|
|
12805
|
-
"data-diff-approval-badge": files.length,
|
|
12806
|
-
"data-active": open ? "" : void 0,
|
|
12807
|
-
"aria-label": t("panel.aria"),
|
|
12808
|
-
"aria-expanded": open,
|
|
12809
|
-
onClick: toggleOpen,
|
|
12810
|
-
children: [
|
|
12811
|
-
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconListPenOutline16, { size: wide ? 16 : 18 }),
|
|
12812
|
-
wide && (0, react_jsx_runtime.jsx)("span", {
|
|
12813
|
-
className: PendingPanel_module_css_default.badgeLabel,
|
|
12814
|
-
children: t("panel.aria")
|
|
12815
|
-
}),
|
|
12816
|
-
(wide || files.length > 0) && (0, react_jsx_runtime.jsx)("span", {
|
|
12817
|
-
className: PendingPanel_module_css_default.badgeCount,
|
|
12818
|
-
children: files.length
|
|
12819
|
-
})
|
|
12820
|
-
]
|
|
13148
|
+
]
|
|
13149
|
+
})
|
|
12821
13150
|
})
|
|
13151
|
+
]
|
|
13152
|
+
});
|
|
13153
|
+
}
|
|
13154
|
+
//#endregion
|
|
13155
|
+
//#region lib/types/client/SettingsTab.js
|
|
13156
|
+
/** DSH Settings top-level section for this plugin's preferences. */
|
|
13157
|
+
/** A pill picker offering the two boolean states 打开 / 关闭. */
|
|
13158
|
+
function OnOffPicker({ value, open, onOpenChange, onSelect, dataAttribute, t }) {
|
|
13159
|
+
return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
13160
|
+
open,
|
|
13161
|
+
onClose: () => {
|
|
13162
|
+
onOpenChange(false);
|
|
13163
|
+
},
|
|
13164
|
+
items: [{
|
|
13165
|
+
id: "on",
|
|
13166
|
+
label: t("action.toggleOn")
|
|
13167
|
+
}, {
|
|
13168
|
+
id: "off",
|
|
13169
|
+
label: t("action.toggleOff")
|
|
13170
|
+
}],
|
|
13171
|
+
selectedId: value ? "on" : "off",
|
|
13172
|
+
onSelect: (id) => {
|
|
13173
|
+
onOpenChange(false);
|
|
13174
|
+
onSelect(id === "on");
|
|
13175
|
+
},
|
|
13176
|
+
align: "end",
|
|
13177
|
+
portal: true,
|
|
13178
|
+
anchor: (0, react_jsx_runtime.jsxs)("button", {
|
|
13179
|
+
type: "button",
|
|
13180
|
+
className: PendingPanel_module_css_default.settingsSelector,
|
|
13181
|
+
"aria-haspopup": "menu",
|
|
13182
|
+
"aria-expanded": open,
|
|
13183
|
+
onClick: () => {
|
|
13184
|
+
onOpenChange(!open);
|
|
13185
|
+
},
|
|
13186
|
+
[dataAttribute]: true,
|
|
13187
|
+
children: [value ? t("action.toggleOn") : t("action.toggleOff"), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: PendingPanel_module_css_default.settingsSelectorChevron })]
|
|
13188
|
+
})
|
|
13189
|
+
});
|
|
13190
|
+
}
|
|
13191
|
+
/** One Agent-preset-style preference row: title + description, pill picker right. */
|
|
13192
|
+
function PreferenceRow({ title, description, value, open, onOpenChange, onSelect, dataAttribute, t }) {
|
|
13193
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
13194
|
+
className: PendingPanel_module_css_default.settingsRow,
|
|
13195
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
13196
|
+
className: PendingPanel_module_css_default.settingsRowText,
|
|
13197
|
+
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
13198
|
+
className: PendingPanel_module_css_default.settingsRowTitle,
|
|
13199
|
+
children: title
|
|
13200
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
13201
|
+
className: PendingPanel_module_css_default.settingsRowDesc,
|
|
13202
|
+
children: description
|
|
13203
|
+
})]
|
|
13204
|
+
}), (0, react_jsx_runtime.jsx)(OnOffPicker, {
|
|
13205
|
+
value,
|
|
13206
|
+
open,
|
|
13207
|
+
onOpenChange,
|
|
13208
|
+
onSelect,
|
|
13209
|
+
dataAttribute,
|
|
13210
|
+
t
|
|
13211
|
+
})]
|
|
13212
|
+
});
|
|
13213
|
+
}
|
|
13214
|
+
/**
|
|
13215
|
+
* The plugin's preferences: auto-paste a copied reference into the input, and
|
|
13216
|
+
* whether importing workspace VCS changes includes untracked files. Each row
|
|
13217
|
+
* mirrors the harness's Agent-preset row (title + description on the left, a
|
|
13218
|
+
* pill picker on the right) with the two boolean states 打开 / 关闭.
|
|
13219
|
+
*/
|
|
13220
|
+
function DiffApprovalSettingsTab({ t }) {
|
|
13221
|
+
const [pasteOnCopy, setPasteOnCopyState] = (0, react.useState)(pasteOnCopyEnabled);
|
|
13222
|
+
const [pasteOnCopyOpen, setPasteOnCopyOpen] = (0, react.useState)(false);
|
|
13223
|
+
const [includeUntracked, setIncludeUntrackedState] = (0, react.useState)(includeUntrackedEnabled);
|
|
13224
|
+
const [includeUntrackedOpen, setIncludeUntrackedOpen] = (0, react.useState)(false);
|
|
13225
|
+
const setPasteOnCopy = (value) => {
|
|
13226
|
+
setPasteOnCopyState(value);
|
|
13227
|
+
setPasteOnCopyEnabled(value);
|
|
13228
|
+
};
|
|
13229
|
+
const setIncludeUntracked = (value) => {
|
|
13230
|
+
setIncludeUntrackedState(value);
|
|
13231
|
+
setIncludeUntrackedEnabled(value);
|
|
13232
|
+
};
|
|
13233
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
13234
|
+
className: PendingPanel_module_css_default.settingsPage,
|
|
13235
|
+
"data-diff-settings": true,
|
|
13236
|
+
children: [(0, react_jsx_runtime.jsx)(PreferenceRow, {
|
|
13237
|
+
title: t("panel.pasteOnCopy"),
|
|
13238
|
+
description: t("panel.pasteOnCopyDesc"),
|
|
13239
|
+
value: pasteOnCopy,
|
|
13240
|
+
open: pasteOnCopyOpen,
|
|
13241
|
+
onOpenChange: setPasteOnCopyOpen,
|
|
13242
|
+
onSelect: setPasteOnCopy,
|
|
13243
|
+
dataAttribute: "data-diff-paste-on-copy-select",
|
|
13244
|
+
t
|
|
13245
|
+
}), (0, react_jsx_runtime.jsx)(PreferenceRow, {
|
|
13246
|
+
title: t("panel.importUntracked"),
|
|
13247
|
+
description: t("panel.importUntrackedDesc"),
|
|
13248
|
+
value: includeUntracked,
|
|
13249
|
+
open: includeUntrackedOpen,
|
|
13250
|
+
onOpenChange: setIncludeUntrackedOpen,
|
|
13251
|
+
onSelect: setIncludeUntracked,
|
|
13252
|
+
dataAttribute: "data-diff-import-untracked-select",
|
|
13253
|
+
t
|
|
12822
13254
|
})]
|
|
12823
13255
|
});
|
|
12824
13256
|
}
|
|
@@ -12867,6 +13299,18 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12867
13299
|
block
|
|
12868
13300
|
}));
|
|
12869
13301
|
},
|
|
13302
|
+
async undo(sessionId) {
|
|
13303
|
+
return actionOf(await rpc.call(DIFF_APPROVAL_CHANNEL, "undo", { sessionId }));
|
|
13304
|
+
},
|
|
13305
|
+
async redo(sessionId) {
|
|
13306
|
+
return actionOf(await rpc.call(DIFF_APPROVAL_CHANNEL, "redo", { sessionId }));
|
|
13307
|
+
},
|
|
13308
|
+
async importVcs(sessionId, includeUntracked) {
|
|
13309
|
+
return importValueOf(await rpc.call(DIFF_APPROVAL_CHANNEL, "vcs-import", {
|
|
13310
|
+
sessionId,
|
|
13311
|
+
includeUntracked
|
|
13312
|
+
}));
|
|
13313
|
+
},
|
|
12870
13314
|
async open(sessionId, id, action) {
|
|
12871
13315
|
return openOf(await rpc.call(DIFF_APPROVAL_CHANNEL, "open", {
|
|
12872
13316
|
sessionId,
|
|
@@ -12923,8 +13367,25 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12923
13367
|
const value = result.value;
|
|
12924
13368
|
if (typeof value !== "object" || value === null) throw new Error("the action returned a malformed value");
|
|
12925
13369
|
const outcome = value.outcome;
|
|
12926
|
-
if (outcome !== "kept" && outcome !== "reverted" && outcome !== "missing") throw new Error("the action returned a malformed outcome");
|
|
12927
|
-
|
|
13370
|
+
if (outcome !== "kept" && outcome !== "reverted" && outcome !== "missing" && outcome !== "undone" && outcome !== "redone" && outcome !== "nothing") throw new Error("the action returned a malformed outcome");
|
|
13371
|
+
const id = value.id;
|
|
13372
|
+
return {
|
|
13373
|
+
outcome,
|
|
13374
|
+
id: typeof id === "string" && id.length > 0 ? id : void 0
|
|
13375
|
+
};
|
|
13376
|
+
}
|
|
13377
|
+
/** Narrow the vcs-import endpoint's value; a malformed wire value is a failure. */
|
|
13378
|
+
function importValueOf(result) {
|
|
13379
|
+
if (!result.ok) throw new Error(`${result.error.code}: ${result.error.message}`);
|
|
13380
|
+
const value = result.value;
|
|
13381
|
+
if (typeof value !== "object" || value === null) throw new Error("the import returned a malformed value");
|
|
13382
|
+
const imported = value.imported;
|
|
13383
|
+
const detected = value.detected;
|
|
13384
|
+
if (typeof imported !== "number" || typeof detected !== "boolean") throw new Error("the import returned a malformed value");
|
|
13385
|
+
return {
|
|
13386
|
+
imported,
|
|
13387
|
+
detected
|
|
13388
|
+
};
|
|
12928
13389
|
}
|
|
12929
13390
|
/** Narrow the open endpoint's value; a malformed wire value is an open failure. */
|
|
12930
13391
|
function openOf(result) {
|
|
@@ -12946,6 +13407,10 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12946
13407
|
*/
|
|
12947
13408
|
/** An empty busy set reused as the snapshot's canonical absent value. */
|
|
12948
13409
|
const EMPTY_BUSY = /* @__PURE__ */ new Set();
|
|
13410
|
+
/** An empty failure map reused as the snapshot's canonical absent value. */
|
|
13411
|
+
const EMPTY_FAILED = /* @__PURE__ */ new Map();
|
|
13412
|
+
/** How long a failed keep/revert hint stays visible before it auto-clears. */
|
|
13413
|
+
const FAILED_HINT_MS = 5e3;
|
|
12949
13414
|
/**
|
|
12950
13415
|
* Create the store over the review-channel port.
|
|
12951
13416
|
* @param port - the typed channel port.
|
|
@@ -12962,22 +13427,51 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12962
13427
|
snapshot = next;
|
|
12963
13428
|
for (const listener of [...listeners]) listener();
|
|
12964
13429
|
};
|
|
13430
|
+
const failedOf = (value) => value.failed ?? EMPTY_FAILED;
|
|
13431
|
+
/** Record one entry's failed keep/revert with its message; auto-clears after a few seconds. */
|
|
13432
|
+
const markFailed = (id, message) => {
|
|
13433
|
+
publish({
|
|
13434
|
+
...snapshot,
|
|
13435
|
+
failed: new Map([...failedOf(snapshot), [id, message]])
|
|
13436
|
+
});
|
|
13437
|
+
window.setTimeout(() => {
|
|
13438
|
+
if (failedOf(snapshot).get(id) !== message) return;
|
|
13439
|
+
const next = new Map(failedOf(snapshot));
|
|
13440
|
+
next.delete(id);
|
|
13441
|
+
publish({
|
|
13442
|
+
...snapshot,
|
|
13443
|
+
failed: next
|
|
13444
|
+
});
|
|
13445
|
+
}, FAILED_HINT_MS);
|
|
13446
|
+
};
|
|
13447
|
+
/** Drop one entry's failure marker after a successful retry. */
|
|
13448
|
+
const clearFailed = (id) => {
|
|
13449
|
+
if (!failedOf(snapshot).has(id)) return;
|
|
13450
|
+
const next = new Map(failedOf(snapshot));
|
|
13451
|
+
next.delete(id);
|
|
13452
|
+
publish({
|
|
13453
|
+
...snapshot,
|
|
13454
|
+
failed: next
|
|
13455
|
+
});
|
|
13456
|
+
};
|
|
12965
13457
|
const withBusy = async (id, action) => {
|
|
12966
13458
|
const { error: _cleared, ...base } = snapshot;
|
|
12967
13459
|
publish({
|
|
12968
13460
|
...base,
|
|
13461
|
+
failed: failedOf(snapshot),
|
|
12969
13462
|
busy: /* @__PURE__ */ new Set([...snapshot.busy, id])
|
|
12970
13463
|
});
|
|
12971
13464
|
try {
|
|
12972
13465
|
await action();
|
|
12973
13466
|
} catch (error) {
|
|
13467
|
+
markFailed(id, error instanceof Error ? error.message : String(error));
|
|
12974
13468
|
publish({
|
|
12975
13469
|
...snapshot,
|
|
12976
|
-
error: error instanceof Error ? error.message : String(error),
|
|
12977
13470
|
busy: new Set([...snapshot.busy].filter((busy) => busy !== id))
|
|
12978
13471
|
});
|
|
12979
13472
|
return;
|
|
12980
13473
|
}
|
|
13474
|
+
clearFailed(id);
|
|
12981
13475
|
publish({
|
|
12982
13476
|
...snapshot,
|
|
12983
13477
|
files: snapshot.files.filter((file) => file.id !== id),
|
|
@@ -12997,7 +13491,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12997
13491
|
publish({
|
|
12998
13492
|
read: true,
|
|
12999
13493
|
files: [],
|
|
13000
|
-
busy: EMPTY_BUSY
|
|
13494
|
+
busy: EMPTY_BUSY,
|
|
13495
|
+
failed: failedOf(snapshot)
|
|
13001
13496
|
});
|
|
13002
13497
|
return;
|
|
13003
13498
|
}
|
|
@@ -13007,7 +13502,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13007
13502
|
read: true,
|
|
13008
13503
|
files,
|
|
13009
13504
|
workspacePath,
|
|
13010
|
-
busy: EMPTY_BUSY
|
|
13505
|
+
busy: EMPTY_BUSY,
|
|
13506
|
+
failed: failedOf(snapshot)
|
|
13011
13507
|
});
|
|
13012
13508
|
} catch (error) {
|
|
13013
13509
|
publish({
|
|
@@ -13015,7 +13511,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13015
13511
|
files: snapshot.files,
|
|
13016
13512
|
workspacePath: snapshot.workspacePath,
|
|
13017
13513
|
error: error instanceof Error ? error.message : String(error),
|
|
13018
|
-
busy: snapshot.busy
|
|
13514
|
+
busy: snapshot.busy,
|
|
13515
|
+
failed: failedOf(snapshot)
|
|
13019
13516
|
});
|
|
13020
13517
|
}
|
|
13021
13518
|
},
|
|
@@ -13038,13 +13535,14 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13038
13535
|
try {
|
|
13039
13536
|
await port.blockKeep(sessionId, id, block);
|
|
13040
13537
|
} catch (error) {
|
|
13538
|
+
markFailed(id, error instanceof Error ? error.message : String(error));
|
|
13041
13539
|
publish({
|
|
13042
13540
|
...snapshot,
|
|
13043
|
-
error: error instanceof Error ? error.message : String(error),
|
|
13044
13541
|
busy: new Set([...snapshot.busy].filter((busy) => busy !== id))
|
|
13045
13542
|
});
|
|
13046
13543
|
return;
|
|
13047
13544
|
}
|
|
13545
|
+
clearFailed(id);
|
|
13048
13546
|
await this.refresh(sessionId);
|
|
13049
13547
|
},
|
|
13050
13548
|
async blockRevert(sessionId, id, block) {
|
|
@@ -13056,15 +13554,41 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13056
13554
|
try {
|
|
13057
13555
|
await port.blockRevert(sessionId, id, block);
|
|
13058
13556
|
} catch (error) {
|
|
13557
|
+
markFailed(id, error instanceof Error ? error.message : String(error));
|
|
13059
13558
|
publish({
|
|
13060
13559
|
...snapshot,
|
|
13061
|
-
error: error instanceof Error ? error.message : String(error),
|
|
13062
13560
|
busy: new Set([...snapshot.busy].filter((busy) => busy !== id))
|
|
13063
13561
|
});
|
|
13064
13562
|
return;
|
|
13065
13563
|
}
|
|
13564
|
+
clearFailed(id);
|
|
13066
13565
|
await this.refresh(sessionId);
|
|
13067
13566
|
},
|
|
13567
|
+
async undo(sessionId) {
|
|
13568
|
+
try {
|
|
13569
|
+
const value = await port.undo(sessionId);
|
|
13570
|
+
await this.refresh(sessionId);
|
|
13571
|
+
const id = value.id;
|
|
13572
|
+
return id !== void 0 && snapshot.files.some((file) => file.id === id) ? id : void 0;
|
|
13573
|
+
} catch {
|
|
13574
|
+
return;
|
|
13575
|
+
}
|
|
13576
|
+
},
|
|
13577
|
+
async redo(sessionId) {
|
|
13578
|
+
try {
|
|
13579
|
+
const value = await port.redo(sessionId);
|
|
13580
|
+
await this.refresh(sessionId);
|
|
13581
|
+
const id = value.id;
|
|
13582
|
+
return id !== void 0 && snapshot.files.some((file) => file.id === id) ? id : void 0;
|
|
13583
|
+
} catch {
|
|
13584
|
+
return;
|
|
13585
|
+
}
|
|
13586
|
+
},
|
|
13587
|
+
async importVcs(sessionId, includeUntracked) {
|
|
13588
|
+
const value = await port.importVcs(sessionId, includeUntracked);
|
|
13589
|
+
await this.refresh(sessionId);
|
|
13590
|
+
return value;
|
|
13591
|
+
},
|
|
13068
13592
|
async open(sessionId, id, action) {
|
|
13069
13593
|
try {
|
|
13070
13594
|
await port.open(sessionId, id, action);
|
|
@@ -13104,11 +13628,19 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13104
13628
|
"panel.missing": "文件已不存在",
|
|
13105
13629
|
"panel.missingHint": "该文件已不存在,回退会恢复该文件。",
|
|
13106
13630
|
"panel.createHint": "回退会删除该新建的文件。",
|
|
13631
|
+
"panel.pasteOnCopy": "复制引用后自动粘贴到消息输入框",
|
|
13632
|
+
"panel.pasteOnCopyDesc": "开启后,复制的引用会自动填入消息输入框,输入框会获得焦点。",
|
|
13633
|
+
"panel.importUntracked": "导入未跟踪的文件改动",
|
|
13634
|
+
"panel.importUntrackedDesc": "开启后,导入工作区改动会包含未跟踪/未版本化的新增文件(Git 未跟踪、SVN 未版本化、Perforce 未版本化)。收集改动需要扫描整个工作区,文件数量大时可能较慢。",
|
|
13635
|
+
"settings.tabLabel": "改动审批",
|
|
13107
13636
|
"row.create": "新增文件",
|
|
13637
|
+
"row.failed": "失败",
|
|
13108
13638
|
"row.added": "+{added}",
|
|
13109
13639
|
"row.removed": "-{removed}",
|
|
13110
13640
|
"action.keep": "保留",
|
|
13111
13641
|
"action.revert": "回退",
|
|
13642
|
+
"action.keepAll": "全部保留",
|
|
13643
|
+
"action.revertAll": "全部回退",
|
|
13112
13644
|
"action.openFile": "打开文件",
|
|
13113
13645
|
"action.revealFile": "打开所在目录",
|
|
13114
13646
|
"action.busy": "处理中…",
|
|
@@ -13119,7 +13651,16 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13119
13651
|
"action.langAuto": "自动",
|
|
13120
13652
|
"action.langAutoDetected": "自动:{lang}",
|
|
13121
13653
|
"action.langSelect": "高亮语言",
|
|
13654
|
+
"action.toggleOn": "打开",
|
|
13655
|
+
"action.toggleOff": "关闭",
|
|
13656
|
+
"action.importVcs": "导入工作区改动",
|
|
13657
|
+
"action.importVcsBusy": "导入中…",
|
|
13658
|
+
"panel.importNone": "没有可导入的改动",
|
|
13659
|
+
"panel.importDone": "已导入 {count} 个改动",
|
|
13660
|
+
"panel.importNoVcs": "未检测到版本控制(Git / SVN / Perforce)",
|
|
13661
|
+
"panel.importFailed": "导入失败:{message}",
|
|
13122
13662
|
"action.search": "搜索 (Ctrl+F)",
|
|
13663
|
+
"action.settings": "设置",
|
|
13123
13664
|
"action.expand": "展开全屏",
|
|
13124
13665
|
"action.exitFullscreen": "退出全屏",
|
|
13125
13666
|
"action.close": "关闭",
|
|
@@ -13143,11 +13684,19 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13143
13684
|
"panel.missing": "File is gone",
|
|
13144
13685
|
"panel.missingHint": "This file no longer exists; reverting restores it.",
|
|
13145
13686
|
"panel.createHint": "Reverting removes this created file.",
|
|
13687
|
+
"panel.pasteOnCopy": "Paste the copied reference into the composer",
|
|
13688
|
+
"panel.pasteOnCopyDesc": "When enabled, a copied reference is pasted into the composer, which then receives focus.",
|
|
13689
|
+
"panel.importUntracked": "Import changes to untracked files",
|
|
13690
|
+
"panel.importUntrackedDesc": "When enabled, importing workspace changes includes new/untracked files (Git-untracked, SVN-unversioned, Perforce-unversioned). Collecting changes scans the whole workspace, which can be slow on large trees.",
|
|
13691
|
+
"settings.tabLabel": "Diff Approval",
|
|
13146
13692
|
"row.create": "New file",
|
|
13693
|
+
"row.failed": "Failed",
|
|
13147
13694
|
"row.added": "+{added}",
|
|
13148
13695
|
"row.removed": "-{removed}",
|
|
13149
13696
|
"action.keep": "Keep",
|
|
13150
13697
|
"action.revert": "Revert",
|
|
13698
|
+
"action.keepAll": "Keep all",
|
|
13699
|
+
"action.revertAll": "Revert all",
|
|
13151
13700
|
"action.openFile": "Open file",
|
|
13152
13701
|
"action.revealFile": "Reveal in folder",
|
|
13153
13702
|
"action.busy": "Working…",
|
|
@@ -13158,7 +13707,16 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13158
13707
|
"action.langAuto": "Auto",
|
|
13159
13708
|
"action.langAutoDetected": "Auto: {lang}",
|
|
13160
13709
|
"action.langSelect": "Highlight language",
|
|
13710
|
+
"action.toggleOn": "On",
|
|
13711
|
+
"action.toggleOff": "Off",
|
|
13712
|
+
"action.importVcs": "Import workspace changes",
|
|
13713
|
+
"action.importVcsBusy": "Importing…",
|
|
13714
|
+
"panel.importNone": "No changes to import",
|
|
13715
|
+
"panel.importDone": "Imported {count} changes",
|
|
13716
|
+
"panel.importNoVcs": "No version control detected (Git / SVN / Perforce)",
|
|
13717
|
+
"panel.importFailed": "Import failed: {message}",
|
|
13161
13718
|
"action.search": "Search (Ctrl+F)",
|
|
13719
|
+
"action.settings": "Settings",
|
|
13162
13720
|
"action.expand": "Expand fullscreen",
|
|
13163
13721
|
"action.exitFullscreen": "Exit fullscreen",
|
|
13164
13722
|
"action.close": "Close",
|
|
@@ -13185,6 +13743,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13185
13743
|
zh,
|
|
13186
13744
|
en
|
|
13187
13745
|
}), "ui-diff-approval: dictionaries");
|
|
13746
|
+
const t = ctx.locale.bind(NS);
|
|
13188
13747
|
const store = createPendingDiffStore(createDiffApprovalPort(ctx.get("connection").rpc));
|
|
13189
13748
|
ctx.on("connection/reset", () => {
|
|
13190
13749
|
store.reset();
|
|
@@ -13202,9 +13761,29 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13202
13761
|
onRevert: (sessionId, path) => store.revert(sessionId, path),
|
|
13203
13762
|
onBlockKeep: (sessionId, id, block) => store.blockKeep(sessionId, id, block),
|
|
13204
13763
|
onBlockRevert: (sessionId, id, block) => store.blockRevert(sessionId, id, block),
|
|
13205
|
-
onOpen: (sessionId, id, action) => store.open(sessionId, id, action)
|
|
13764
|
+
onOpen: (sessionId, id, action) => store.open(sessionId, id, action),
|
|
13765
|
+
onUndo: (sessionId) => store.undo(sessionId),
|
|
13766
|
+
onRedo: (sessionId) => store.redo(sessionId),
|
|
13767
|
+
onImportVcs: (sessionId, includeUntracked) => store.importVcs(sessionId, includeUntracked),
|
|
13768
|
+
onPasteReference: (sessionId, reference) => {
|
|
13769
|
+
const actx = ctx.get("sessions")?.scope(sessionId);
|
|
13770
|
+
if (actx === void 0) return;
|
|
13771
|
+
const conversation = actx.get("conversation");
|
|
13772
|
+
if (conversation?.input === void 0) return;
|
|
13773
|
+
const textarea = document.querySelector("[data-composer-card] textarea");
|
|
13774
|
+
const base = textarea?.value ?? "";
|
|
13775
|
+
conversation.input.for(actx).setDraft(base === "" ? reference : `${base} ${reference}`);
|
|
13776
|
+
textarea?.focus();
|
|
13777
|
+
}
|
|
13206
13778
|
})
|
|
13207
13779
|
}, PendingPanel));
|
|
13780
|
+
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
|
13781
|
+
name: "settings.section",
|
|
13782
|
+
id: "diff-approval",
|
|
13783
|
+
order: 100,
|
|
13784
|
+
label: () => t("settings.tabLabel"),
|
|
13785
|
+
locale: NS
|
|
13786
|
+
}, DiffApprovalSettingsTab));
|
|
13208
13787
|
}
|
|
13209
13788
|
//#endregion
|
|
13210
13789
|
exports.DIFF_APPROVAL_CHANNEL = DIFF_APPROVAL_CHANNEL;
|