dsh-diff-approval 0.8.0 → 0.10.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 +4 -3
- package/README.zh.md +4 -3
- package/docs/images/pending-panel.png +0 -0
- package/docs/images/pending-panel.zh.png +0 -0
- package/lib/client.js +739 -189
- package/lib/index.js +104 -25
- package/lib/types/client/PendingPanel.d.ts +2 -1
- package/lib/types/client/SettingsTab.d.ts +5 -4
- package/lib/types/client/locales.d.ts +14 -0
- package/lib/types/client/settings.d.ts +19 -0
- package/lib/types/client/slots.d.ts +6 -0
- package/lib/types/client/store.d.ts +2 -0
- package/lib/types/types.d.ts +4 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -11624,6 +11624,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11624
11624
|
/** Client preferences for the review panel, persisted in localStorage. */
|
|
11625
11625
|
const PASTE_ON_COPY_KEY = "diff-approval:paste-on-copy";
|
|
11626
11626
|
const IMPORT_UNTRACKED_KEY = "diff-approval:import-untracked";
|
|
11627
|
+
const TAB_WIDTH_KEY = "diff-approval:tab-size";
|
|
11628
|
+
const WRAP_PREFIX = "diff-approval:wrap:";
|
|
11627
11629
|
/**
|
|
11628
11630
|
* Whether copying a reference should also paste it into the chat input and
|
|
11629
11631
|
* focus it. Defaults to on; only an explicit `'0'` disables it.
|
|
@@ -11650,9 +11652,37 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11650
11652
|
function setIncludeUntrackedEnabled(value) {
|
|
11651
11653
|
localStorage.setItem(IMPORT_UNTRACKED_KEY, value ? "1" : "0");
|
|
11652
11654
|
}
|
|
11655
|
+
/**
|
|
11656
|
+
* Whether lines wrap (auto-wrap) in the diff for one highlight language.
|
|
11657
|
+
* Defaults to off; only an explicit `'1'` enables it. Stored per language, so
|
|
11658
|
+
* a language's preference never leaks into another's.
|
|
11659
|
+
* @param lang - the highlight language (or `''` for the auto/default bucket).
|
|
11660
|
+
* @returns whether lines wrap.
|
|
11661
|
+
*/
|
|
11662
|
+
function wrapEnabled(lang) {
|
|
11663
|
+
return localStorage.getItem(`${WRAP_PREFIX}${lang}`) === "1";
|
|
11664
|
+
}
|
|
11665
|
+
/** Persist the per-language auto-wrap preference. */
|
|
11666
|
+
function setWrapEnabled(lang, value) {
|
|
11667
|
+
localStorage.setItem(`${WRAP_PREFIX}${lang}`, value ? "1" : "0");
|
|
11668
|
+
}
|
|
11669
|
+
/**
|
|
11670
|
+
* The diff's tab width in spaces. Defaults to 4; the settings UI offers 2/4/8,
|
|
11671
|
+
* but any positive integer is accepted. This drives both the rendered
|
|
11672
|
+
* `tab-size` and the wrapped-line tab measurement, so they always agree.
|
|
11673
|
+
* @returns the number of spaces one tab advances.
|
|
11674
|
+
*/
|
|
11675
|
+
function tabWidth() {
|
|
11676
|
+
const value = Number.parseInt(localStorage.getItem(TAB_WIDTH_KEY) ?? "", 10);
|
|
11677
|
+
return Number.isInteger(value) && value > 0 ? value : 4;
|
|
11678
|
+
}
|
|
11679
|
+
/** Persist the diff's tab width (in spaces). */
|
|
11680
|
+
function setTabWidth(value) {
|
|
11681
|
+
localStorage.setItem(TAB_WIDTH_KEY, String(value));
|
|
11682
|
+
}
|
|
11653
11683
|
//#endregion
|
|
11654
11684
|
//#region \0dsh-css:/home/runner/work/dsh-diff-approval/dsh-diff-approval/src/client/PendingPanel.module.css.mjs
|
|
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}";
|
|
11685
|
+
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;position:relative}.F1KBNa_fileListFloat{z-index:40;box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);box-shadow:var(--dsw-shadow-lv2);border-radius:12px;flex-direction:column;padding:6px 8px 10px;display:flex;position:absolute;overflow:hidden}.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;gap:8px;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}.F1KBNa_notice{z-index:60;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);max-width:360px;box-shadow:var(--dsw-shadow-lv3);border-radius:10px;align-items:flex-start;gap:12px;padding:12px 14px;display:flex;position:fixed;bottom:24px;right:24px}.F1KBNa_noticeText{font:var(--dsw-font-caption);color:var(--dsw-alias-label-primary);flex:1;margin:0;line-height:1.45}.F1KBNa_noticeButton{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);font:var(--dsw-font-caption);cursor:pointer;border-radius:6px;flex:none;padding:4px 10px}.F1KBNa_noticeButton:hover{background:var(--dsw-alias-interactive-bg-hover-solid)}.F1KBNa_wrap .F1KBNa_line{height:auto;min-height:22px}.F1KBNa_subline{white-space:pre;height:22px;line-height:22px;display:block;overflow:hidden}.F1KBNa_wrapActive{background:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50)}.F1KBNa_wrapActive:hover{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 85%, var(--dsw-static-neutral-bluish-1000))}";
|
|
11656
11686
|
const tagId = "dsh-diff-approval/PendingPanel.module.css";
|
|
11657
11687
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
11658
11688
|
const tag = document.createElement("style");
|
|
@@ -11662,92 +11692,99 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11662
11692
|
document.head.appendChild(tag);
|
|
11663
11693
|
}
|
|
11664
11694
|
var PendingPanel_module_css_default = {
|
|
11665
|
-
"
|
|
11695
|
+
"badge": "F1KBNa_badge",
|
|
11666
11696
|
"panel": "F1KBNa_panel",
|
|
11667
|
-
"
|
|
11668
|
-
"
|
|
11669
|
-
"
|
|
11670
|
-
"row": "F1KBNa_row",
|
|
11671
|
-
"title": "F1KBNa_title",
|
|
11672
|
-
"blockActions": "F1KBNa_blockActions",
|
|
11673
|
-
"langLabel": "F1KBNa_langLabel",
|
|
11674
|
-
"detailEmpty": "F1KBNa_detailEmpty",
|
|
11675
|
-
"del": "F1KBNa_del",
|
|
11676
|
-
"listScroll": "F1KBNa_listScroll",
|
|
11677
|
-
"close": "F1KBNa_close",
|
|
11678
|
-
"group": "F1KBNa_group",
|
|
11697
|
+
"settingsRow": "F1KBNa_settingsRow",
|
|
11698
|
+
"searchBar": "F1KBNa_searchBar",
|
|
11699
|
+
"detail": "F1KBNa_detail",
|
|
11679
11700
|
"diffActions": "F1KBNa_diffActions",
|
|
11680
|
-
"
|
|
11681
|
-
"states": "F1KBNa_states",
|
|
11682
|
-
"searchInput": "F1KBNa_searchInput",
|
|
11683
|
-
"settingsRowText": "F1KBNa_settingsRowText",
|
|
11684
|
-
"note": "F1KBNa_note",
|
|
11685
|
-
"addCount": "F1KBNa_addCount",
|
|
11686
|
-
"layer": "F1KBNa_layer",
|
|
11701
|
+
"markerAdd": "F1KBNa_markerAdd",
|
|
11687
11702
|
"diff": "F1KBNa_diff",
|
|
11688
|
-
"
|
|
11689
|
-
"
|
|
11690
|
-
"
|
|
11691
|
-
"actionQuietDisabled": "F1KBNa_actionQuietDisabled",
|
|
11692
|
-
"searchCount": "F1KBNa_searchCount",
|
|
11693
|
-
"badgeCount": "F1KBNa_badgeCount",
|
|
11694
|
-
"context": "F1KBNa_context",
|
|
11695
|
-
"settingsSelectorChevron": "F1KBNa_settingsSelectorChevron",
|
|
11696
|
-
"kindHint": "F1KBNa_kindHint",
|
|
11697
|
-
"footerButtons": "F1KBNa_footerButtons",
|
|
11703
|
+
"gutter": "F1KBNa_gutter",
|
|
11704
|
+
"missingHint": "F1KBNa_missingHint",
|
|
11705
|
+
"wrap": "F1KBNa_wrap",
|
|
11698
11706
|
"diffHeader": "F1KBNa_diffHeader",
|
|
11699
|
-
"
|
|
11707
|
+
"context": "F1KBNa_context",
|
|
11708
|
+
"importNote": "F1KBNa_importNote",
|
|
11709
|
+
"divergedHint": "F1KBNa_divergedHint",
|
|
11710
|
+
"listScroll": "F1KBNa_listScroll",
|
|
11700
11711
|
"statusBar": "F1KBNa_statusBar",
|
|
11701
|
-
"
|
|
11702
|
-
"
|
|
11703
|
-
"
|
|
11704
|
-
"markerAdd": "F1KBNa_markerAdd",
|
|
11705
|
-
"header": "F1KBNa_header",
|
|
11706
|
-
"settingsRowTitle": "F1KBNa_settingsRowTitle",
|
|
11712
|
+
"readError": "F1KBNa_readError",
|
|
11713
|
+
"settingsRowDesc": "F1KBNa_settingsRowDesc",
|
|
11714
|
+
"settingsRowText": "F1KBNa_settingsRowText",
|
|
11707
11715
|
"emptyState": "F1KBNa_emptyState",
|
|
11716
|
+
"langLabel": "F1KBNa_langLabel",
|
|
11717
|
+
"expandExpanded": "F1KBNa_expandExpanded",
|
|
11718
|
+
"noticeText": "F1KBNa_noticeText",
|
|
11719
|
+
"addCount": "F1KBNa_addCount",
|
|
11720
|
+
"subline": "F1KBNa_subline",
|
|
11721
|
+
"badgeCount": "F1KBNa_badgeCount",
|
|
11722
|
+
"line": "F1KBNa_line",
|
|
11723
|
+
"header": "F1KBNa_header",
|
|
11724
|
+
"close": "F1KBNa_close",
|
|
11725
|
+
"blockActions": "F1KBNa_blockActions",
|
|
11726
|
+
"actionError": "F1KBNa_actionError",
|
|
11727
|
+
"rows": "F1KBNa_rows",
|
|
11728
|
+
"actionPrimary": "F1KBNa_actionPrimary",
|
|
11729
|
+
"searchCount": "F1KBNa_searchCount",
|
|
11730
|
+
"wrapActive": "F1KBNa_wrapActive",
|
|
11708
11731
|
"rail": "F1KBNa_rail",
|
|
11709
|
-
"
|
|
11710
|
-
"
|
|
11711
|
-
"
|
|
11732
|
+
"overviewRuler": "F1KBNa_overviewRuler",
|
|
11733
|
+
"diffBody": "F1KBNa_diffBody",
|
|
11734
|
+
"vSpacer": "F1KBNa_vSpacer",
|
|
11735
|
+
"title": "F1KBNa_title",
|
|
11712
11736
|
"rowMeta": "F1KBNa_rowMeta",
|
|
11713
|
-
"actionError": "F1KBNa_actionError",
|
|
11714
11737
|
"diffStats": "F1KBNa_diffStats",
|
|
11715
|
-
"flexSpacer": "F1KBNa_flexSpacer",
|
|
11716
|
-
"diffBody": "F1KBNa_diffBody",
|
|
11717
|
-
"statusAction": "F1KBNa_statusAction",
|
|
11718
|
-
"readError": "F1KBNa_readError",
|
|
11719
|
-
"kindTag": "F1KBNa_kindTag",
|
|
11720
|
-
"delCount": "F1KBNa_delCount",
|
|
11721
11738
|
"blockPosition": "F1KBNa_blockPosition",
|
|
11722
|
-
"
|
|
11723
|
-
"
|
|
11724
|
-
"headerActions": "F1KBNa_headerActions",
|
|
11725
|
-
"divergedHint": "F1KBNa_divergedHint",
|
|
11726
|
-
"code": "F1KBNa_code",
|
|
11739
|
+
"searchInput": "F1KBNa_searchInput",
|
|
11740
|
+
"bulkActions": "F1KBNa_bulkActions",
|
|
11727
11741
|
"noteCentered": "F1KBNa_noteCentered",
|
|
11728
|
-
"expand": "F1KBNa_expand",
|
|
11729
|
-
"vSpacer": "F1KBNa_vSpacer",
|
|
11730
|
-
"importNote": "F1KBNa_importNote",
|
|
11731
|
-
"settingsRow": "F1KBNa_settingsRow",
|
|
11732
|
-
"split": "F1KBNa_split",
|
|
11733
|
-
"missing": "F1KBNa_missing",
|
|
11734
|
-
"actionPrimary": "F1KBNa_actionPrimary",
|
|
11735
11742
|
"blockFlash": "F1KBNa_blockFlash",
|
|
11743
|
+
"actionQuietDisabled": "F1KBNa_actionQuietDisabled",
|
|
11744
|
+
"code": "F1KBNa_code",
|
|
11736
11745
|
"langSelect": "F1KBNa_langSelect",
|
|
11737
|
-
"
|
|
11738
|
-
"
|
|
11739
|
-
"
|
|
11740
|
-
"
|
|
11741
|
-
"
|
|
11742
|
-
"
|
|
11743
|
-
"rowHead": "F1KBNa_rowHead",
|
|
11744
|
-
"searchBar": "F1KBNa_searchBar",
|
|
11746
|
+
"kindTag": "F1KBNa_kindTag",
|
|
11747
|
+
"diffFlash": "F1KBNa_diffFlash",
|
|
11748
|
+
"footerButtons": "F1KBNa_footerButtons",
|
|
11749
|
+
"missing": "F1KBNa_missing",
|
|
11750
|
+
"layer": "F1KBNa_layer",
|
|
11751
|
+
"noticeButton": "F1KBNa_noticeButton",
|
|
11745
11752
|
"fileList": "F1KBNa_fileList",
|
|
11753
|
+
"add": "F1KBNa_add",
|
|
11754
|
+
"split": "F1KBNa_split",
|
|
11755
|
+
"overviewMarker": "F1KBNa_overviewMarker",
|
|
11756
|
+
"resizeHandle": "F1KBNa_resizeHandle",
|
|
11757
|
+
"settingsSelector": "F1KBNa_settingsSelector",
|
|
11758
|
+
"badgeLabel": "F1KBNa_badgeLabel",
|
|
11759
|
+
"fileListFloat": "F1KBNa_fileListFloat",
|
|
11760
|
+
"expand": "F1KBNa_expand",
|
|
11761
|
+
"diffBodyWrap": "F1KBNa_diffBodyWrap",
|
|
11746
11762
|
"lines": "F1KBNa_lines",
|
|
11747
|
-
"
|
|
11748
|
-
"
|
|
11749
|
-
"
|
|
11750
|
-
"
|
|
11763
|
+
"action": "F1KBNa_action",
|
|
11764
|
+
"statusAction": "F1KBNa_statusAction",
|
|
11765
|
+
"notice": "F1KBNa_notice",
|
|
11766
|
+
"fullscreenBackdrop": "F1KBNa_fullscreenBackdrop",
|
|
11767
|
+
"settingsSelectorChevron": "F1KBNa_settingsSelectorChevron",
|
|
11768
|
+
"delCount": "F1KBNa_delCount",
|
|
11769
|
+
"flexSpacer": "F1KBNa_flexSpacer",
|
|
11770
|
+
"markerDel": "F1KBNa_markerDel",
|
|
11771
|
+
"note": "F1KBNa_note",
|
|
11772
|
+
"states": "F1KBNa_states",
|
|
11773
|
+
"rowFailed": "F1KBNa_rowFailed",
|
|
11774
|
+
"settingsPage": "F1KBNa_settingsPage",
|
|
11775
|
+
"rowHead": "F1KBNa_rowHead",
|
|
11776
|
+
"headerActions": "F1KBNa_headerActions",
|
|
11777
|
+
"group": "F1KBNa_group",
|
|
11778
|
+
"settingsRowTitle": "F1KBNa_settingsRowTitle",
|
|
11779
|
+
"rowPath": "F1KBNa_rowPath",
|
|
11780
|
+
"detailEmpty": "F1KBNa_detailEmpty",
|
|
11781
|
+
"iconAction": "F1KBNa_iconAction",
|
|
11782
|
+
"kindHint": "F1KBNa_kindHint",
|
|
11783
|
+
"hint": "F1KBNa_hint",
|
|
11784
|
+
"importButton": "F1KBNa_importButton",
|
|
11785
|
+
"del": "F1KBNa_del",
|
|
11786
|
+
"diffPath": "F1KBNa_diffPath",
|
|
11787
|
+
"row": "F1KBNa_row"
|
|
11751
11788
|
};
|
|
11752
11789
|
//#endregion
|
|
11753
11790
|
//#region lib/types/client/PendingPanel.js
|
|
@@ -11779,8 +11816,144 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11779
11816
|
/** File-list pane width bounds for the manual split drag, in px. */
|
|
11780
11817
|
const MIN_LIST_WIDTH_PX = 160;
|
|
11781
11818
|
const MAX_LIST_WIDTH_PX = 560;
|
|
11819
|
+
/** Inset of the floating file-list card from the code scroll box, in px. */
|
|
11820
|
+
const FLOAT_LIST_MARGIN_PX = 12;
|
|
11782
11821
|
/** Fixed diff-row height in px; the virtual window and jump math are built on it. */
|
|
11783
11822
|
const ROW_HEIGHT_PX = 22;
|
|
11823
|
+
/** Total width of the two line-number gutters, subtracted from the code width
|
|
11824
|
+
* when measuring wrapped line heights. */
|
|
11825
|
+
const WRAP_GUTTERS_PX = 88;
|
|
11826
|
+
/** A shared canvas for measuring wrapped line heights (CPU-only, no DOM reflow). */
|
|
11827
|
+
let measureCanvas;
|
|
11828
|
+
/**
|
|
11829
|
+
* Compute a diff line's visual sub-lines for soft wrap the way VSCode does it:
|
|
11830
|
+
* a Unicode line-break model — break at whitespace and between any two CJK
|
|
11831
|
+
* characters (Chinese han, Japanese kana, fullwidth forms), keep Latin and
|
|
11832
|
+
* numeric words atomic (a word longer than a whole line falls back to a
|
|
11833
|
+
* character split), and honor East Asian kinsoku so an opening bracket never
|
|
11834
|
+
* ends a line and a closing/terminal punctuation never starts one. Tabs
|
|
11835
|
+
* advance to the tab stop derived from the computed `tab-size`. This *is* the
|
|
11836
|
+
* wrap decision — the caller renders the returned sub-lines itself (never
|
|
11837
|
+
* `white-space: pre-wrap`), so the row height equals `subLines.length * 22`
|
|
11838
|
+
* by construction and can never drift from the browser re-wrapping.
|
|
11839
|
+
* The concatenation equals the input (no characters are dropped), so
|
|
11840
|
+
* highlight runs can be clipped back onto sub-lines by character offset.
|
|
11841
|
+
* @param text - the line's content (no trailing newline).
|
|
11842
|
+
* @param widthPx - the available code width, in px.
|
|
11843
|
+
* @param measure - `ctx.measureText` bound to the code font.
|
|
11844
|
+
* @param tabPx - the width of one tab stop, in px.
|
|
11845
|
+
*/
|
|
11846
|
+
const cpOf = (c) => c.codePointAt(0) ?? 0;
|
|
11847
|
+
/** Space, tab, or the ideographic space — whitespace is a break opportunity. */
|
|
11848
|
+
function isSpaceCode(cp) {
|
|
11849
|
+
return cp === 32 || cp === 9 || cp === 12288;
|
|
11850
|
+
}
|
|
11851
|
+
/**
|
|
11852
|
+
* CJK characters — Chinese han, Japanese kana, CJK fullwidth forms. Each is an
|
|
11853
|
+
* independent break opportunity (wrap between any two), unlike Latin words.
|
|
11854
|
+
*/
|
|
11855
|
+
function isCJKCode(cp) {
|
|
11856
|
+
return cp >= 12352 && cp <= 12543 || cp >= 13312 && cp <= 19903 || cp >= 19968 && cp <= 40959 || cp >= 63744 && cp <= 64255 || cp >= 65072 && cp <= 65103 || cp >= 65280 && cp <= 65519 || cp >= 131072 && cp <= 195103;
|
|
11857
|
+
}
|
|
11858
|
+
/** Opening bracket/quote — kinsoku forbids ending a line right after it. */
|
|
11859
|
+
function isOpenPunctCode(cp) {
|
|
11860
|
+
return cp === 40 || cp === 91 || cp === 123 || cp === 12296 || cp === 12298 || cp === 12300 || cp === 12302 || cp === 12304 || cp === 12308 || cp === 12310 || cp === 12312 || cp === 65288 || cp === 65339 || cp === 65371 || cp === 8216 || cp === 8220;
|
|
11861
|
+
}
|
|
11862
|
+
/** Closing bracket/quote or terminal punctuation — kinsoku forbids starting a line with it. */
|
|
11863
|
+
function isClosePunctCode(cp) {
|
|
11864
|
+
return cp === 41 || cp === 93 || cp === 125 || cp === 12289 || cp === 12290 || cp === 12297 || cp === 12299 || cp === 12301 || cp === 12303 || cp === 12305 || cp === 12309 || cp === 12311 || cp === 12313 || cp === 65289 || cp === 65341 || cp === 65373 || cp === 65292 || cp === 65294 || cp === 65281 || cp === 65311 || cp === 65307 || cp === 65306 || cp === 8217 || cp === 8221 || cp === 8230 || cp === 8212;
|
|
11865
|
+
}
|
|
11866
|
+
/**
|
|
11867
|
+
* Whether a line break is allowed between characters `a` (ending the current
|
|
11868
|
+
* line) and `b` (starting the next). Whitespace and any CJK/serial-boundary
|
|
11869
|
+
* admit a break; a full Latin/numeric word does not. Kinsoku forbids a break
|
|
11870
|
+
* after an opening punct or before a closing/terminal one.
|
|
11871
|
+
*/
|
|
11872
|
+
function breakValid(a, b) {
|
|
11873
|
+
const ac = cpOf(a);
|
|
11874
|
+
const bc = cpOf(b);
|
|
11875
|
+
if (isOpenPunctCode(ac)) return false;
|
|
11876
|
+
if (isClosePunctCode(bc)) return false;
|
|
11877
|
+
if (isSpaceCode(ac)) return true;
|
|
11878
|
+
if (isSpaceCode(bc)) return false;
|
|
11879
|
+
if (isCJKCode(ac) || isCJKCode(bc)) return true;
|
|
11880
|
+
return false;
|
|
11881
|
+
}
|
|
11882
|
+
/**
|
|
11883
|
+
* The largest index in `chars` at which a break may occur so the next line can
|
|
11884
|
+
* begin there with the overflowing character `next` (the break may be at the
|
|
11885
|
+
* line's end, `chars.length`). -1 when no position admits a break.
|
|
11886
|
+
*/
|
|
11887
|
+
function lastBreakIndex(chars, next) {
|
|
11888
|
+
for (let k = chars.length; k >= 1; k--) {
|
|
11889
|
+
const a = chars[k - 1];
|
|
11890
|
+
if (breakValid(a, k < chars.length ? chars[k] : next)) return k;
|
|
11891
|
+
}
|
|
11892
|
+
return -1;
|
|
11893
|
+
}
|
|
11894
|
+
/** Width of a code-point array, advancing tabs to the next stop. */
|
|
11895
|
+
function charsWidth(chars, measure, tabPx) {
|
|
11896
|
+
let w = 0;
|
|
11897
|
+
for (const c of chars) if (c === " ") w += tabPx - w % tabPx;
|
|
11898
|
+
else w += measure(c);
|
|
11899
|
+
return w;
|
|
11900
|
+
}
|
|
11901
|
+
function wrapInto(text, widthPx, measure, tabPx) {
|
|
11902
|
+
if (widthPx <= 0) return [text];
|
|
11903
|
+
const codepoints = Array.from(text);
|
|
11904
|
+
if (codepoints.length === 0) return [""];
|
|
11905
|
+
const out = [];
|
|
11906
|
+
let line = [];
|
|
11907
|
+
let lineW = 0;
|
|
11908
|
+
for (const ch of codepoints) {
|
|
11909
|
+
const adv = ch === " " ? tabPx - lineW % tabPx : measure(ch);
|
|
11910
|
+
if (line.length > 0 && lineW + adv > widthPx) {
|
|
11911
|
+
if (isSpaceCode(cpOf(ch))) {
|
|
11912
|
+
line.push(ch);
|
|
11913
|
+
lineW += adv;
|
|
11914
|
+
out.push(line.join(""));
|
|
11915
|
+
line = [];
|
|
11916
|
+
lineW = 0;
|
|
11917
|
+
continue;
|
|
11918
|
+
}
|
|
11919
|
+
const k = lastBreakIndex(line, ch);
|
|
11920
|
+
if (k >= 1) {
|
|
11921
|
+
out.push(line.slice(0, k).join(""));
|
|
11922
|
+
line = line.slice(k);
|
|
11923
|
+
lineW = charsWidth(line, measure, tabPx);
|
|
11924
|
+
} else {
|
|
11925
|
+
out.push(line.join(""));
|
|
11926
|
+
line = [];
|
|
11927
|
+
lineW = 0;
|
|
11928
|
+
}
|
|
11929
|
+
}
|
|
11930
|
+
line.push(ch);
|
|
11931
|
+
lineW += ch === " " ? tabPx - lineW % tabPx : measure(ch);
|
|
11932
|
+
}
|
|
11933
|
+
out.push(line.join(""));
|
|
11934
|
+
if (out.length > 1 && out[out.length - 1] === "") out.pop();
|
|
11935
|
+
return out;
|
|
11936
|
+
}
|
|
11937
|
+
/** Resolve the code cell's computed font for canvas measurement. */
|
|
11938
|
+
function codeFontOf() {
|
|
11939
|
+
const code = document.querySelector("[data-diff-code]");
|
|
11940
|
+
if (code === null) return void 0;
|
|
11941
|
+
const computed = getComputedStyle(code);
|
|
11942
|
+
return computed.font || `${computed.fontStyle} ${computed.fontWeight} ${computed.fontSize} ${computed.fontFamily}`;
|
|
11943
|
+
}
|
|
11944
|
+
/** Create a measurer bound to `font`; falls back to a rough char estimate. */
|
|
11945
|
+
function makeMeasurer(font) {
|
|
11946
|
+
if (typeof document === "undefined") return void 0;
|
|
11947
|
+
try {
|
|
11948
|
+
if (measureCanvas === void 0) measureCanvas = document.createElement("canvas").getContext("2d") ?? void 0;
|
|
11949
|
+
} catch {
|
|
11950
|
+
return;
|
|
11951
|
+
}
|
|
11952
|
+
const ctx = measureCanvas;
|
|
11953
|
+
if (ctx === void 0) return void 0;
|
|
11954
|
+
if (font !== void 0) ctx.font = font;
|
|
11955
|
+
return (text) => ctx.measureText(text).width;
|
|
11956
|
+
}
|
|
11784
11957
|
/** The overview ruler's width in px (mirrors `.overviewRuler`). The flash is
|
|
11785
11958
|
* kept off it even when the scroller has no vertical scrollbar. */
|
|
11786
11959
|
const OVERVIEW_RULER_WIDTH_PX = 4;
|
|
@@ -11790,16 +11963,28 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11790
11963
|
* 5px frame padding on each side + 1px border on each side, plus a little
|
|
11791
11964
|
* breathing room so the bottom padding never sits flush against it. */
|
|
11792
11965
|
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;
|
|
11797
11966
|
/** The trailing file-name segment of a path, used for row display. */
|
|
11798
11967
|
function basenameOf(path) {
|
|
11799
11968
|
const index = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
|
|
11800
11969
|
return index < 0 ? path : path.slice(index + 1);
|
|
11801
11970
|
}
|
|
11802
11971
|
/**
|
|
11972
|
+
* Order two paths by their displayed file name (dictionary, case-insensitive),
|
|
11973
|
+
* breaking a same-name tie on the full path so files in different directories
|
|
11974
|
+
* keep a stable order. The file list shows only the file name, so the panel
|
|
11975
|
+
* sorts by it here — the host's list order (oldest capture first) is not a
|
|
11976
|
+
* display guarantee.
|
|
11977
|
+
*/
|
|
11978
|
+
function compareFileNames(a, b) {
|
|
11979
|
+
const na = basenameOf(a).toLowerCase();
|
|
11980
|
+
const nb = basenameOf(b).toLowerCase();
|
|
11981
|
+
if (na !== nb) return na < nb ? -1 : 1;
|
|
11982
|
+
const pa = a.toLowerCase();
|
|
11983
|
+
const pb = b.toLowerCase();
|
|
11984
|
+
if (pa !== pb) return pa < pb ? -1 : 1;
|
|
11985
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
11986
|
+
}
|
|
11987
|
+
/**
|
|
11803
11988
|
* Open the DSH settings dialog and switch to this plugin's section. The
|
|
11804
11989
|
* settings shell keeps its open state and the active section id as
|
|
11805
11990
|
* component-local viewing state with no cross-plugin service, so the dialog
|
|
@@ -11825,18 +12010,56 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11825
12010
|
/** Empty failure map reused as the snapshot's canonical absent value. */
|
|
11826
12011
|
const EMPTY_FAILED_MAP = /* @__PURE__ */ new Map();
|
|
11827
12012
|
/**
|
|
12013
|
+
* Clip highlight runs (which partition one whole line) to the character range
|
|
12014
|
+
* `[start, end)` of that line, producing the sub-line's highlighted content.
|
|
12015
|
+
*/
|
|
12016
|
+
function clipRuns(runs, start, end) {
|
|
12017
|
+
const nodes = [];
|
|
12018
|
+
let pos = 0;
|
|
12019
|
+
for (const run of runs) {
|
|
12020
|
+
const runStart = pos;
|
|
12021
|
+
const runEnd = pos + run.text.length;
|
|
12022
|
+
pos = runEnd;
|
|
12023
|
+
if (runEnd <= start || runStart >= end) continue;
|
|
12024
|
+
const text = run.text.slice(Math.max(runStart, start) - runStart, Math.min(runEnd, end) - runStart);
|
|
12025
|
+
if (text.length === 0) continue;
|
|
12026
|
+
nodes.push((0, react_jsx_runtime.jsx)("span", {
|
|
12027
|
+
style: run.style,
|
|
12028
|
+
children: text
|
|
12029
|
+
}, nodes.length));
|
|
12030
|
+
}
|
|
12031
|
+
return nodes.length === 0 ? "\xA0" : nodes;
|
|
12032
|
+
}
|
|
12033
|
+
/**
|
|
11828
12034
|
* One rendered diff row, memoized so a poll or an unrelated state change
|
|
11829
12035
|
* does not re-render rows whose content, highlight, and focus are unchanged.
|
|
12036
|
+
* With auto-wrap on, `wrappedLines` carries the row's visual sub-lines and the
|
|
12037
|
+
* code cell renders each at a fixed 22px (never `pre-wrap`), so the row height
|
|
12038
|
+
* is `wrappedLines.length * 22` by construction.
|
|
11830
12039
|
*/
|
|
11831
12040
|
const DiffRow = (0, react.memo)(function DiffRow(props) {
|
|
11832
|
-
const { index, row, runs, focused, searchHit, searchCurrent, onRowHover } = props;
|
|
12041
|
+
const { index, row, runs, focused, searchHit, searchCurrent, onRowHover, wrappedLines } = props;
|
|
11833
12042
|
const lineNumber = row.kind === "del" ? row.oldLine : row.newLine;
|
|
11834
12043
|
const sideRuns = row.kind === "del" ? runs?.oldRuns : runs?.newRuns;
|
|
11835
12044
|
const lineRuns = lineNumber === void 0 ? void 0 : sideRuns?.[lineNumber - 1];
|
|
11836
|
-
|
|
12045
|
+
let code;
|
|
12046
|
+
if (wrappedLines === void 0) code = lineRuns !== void 0 && lineRuns.length > 0 ? lineRuns.map((span, spanIndex) => (0, react_jsx_runtime.jsx)("span", {
|
|
11837
12047
|
style: span.style,
|
|
11838
12048
|
children: span.text
|
|
11839
|
-
}, spanIndex));
|
|
12049
|
+
}, spanIndex)) : row.text === "" ? "\xA0" : row.text;
|
|
12050
|
+
else {
|
|
12051
|
+
const highlighted = lineRuns !== void 0 && lineRuns.length > 0;
|
|
12052
|
+
let offset = 0;
|
|
12053
|
+
code = wrappedLines.map((line, lineIndex) => {
|
|
12054
|
+
const start = offset;
|
|
12055
|
+
offset += line.length;
|
|
12056
|
+
const content = highlighted ? clipRuns(lineRuns, start, offset) : line === "" ? "\xA0" : line;
|
|
12057
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
12058
|
+
className: PendingPanel_module_css_default.subline,
|
|
12059
|
+
children: content
|
|
12060
|
+
}, lineIndex);
|
|
12061
|
+
});
|
|
12062
|
+
}
|
|
11840
12063
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
11841
12064
|
className: `${PendingPanel_module_css_default.line} ${ROW_CLASS[row.kind]}`,
|
|
11842
12065
|
"data-diff-line": row.kind,
|
|
@@ -11858,7 +12081,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11858
12081
|
(0, react_jsx_runtime.jsx)("span", {
|
|
11859
12082
|
className: PendingPanel_module_css_default.code,
|
|
11860
12083
|
"data-diff-code": true,
|
|
11861
|
-
children:
|
|
12084
|
+
children: code
|
|
11862
12085
|
})
|
|
11863
12086
|
]
|
|
11864
12087
|
});
|
|
@@ -12035,7 +12258,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12035
12258
|
});
|
|
12036
12259
|
}
|
|
12037
12260
|
/** The selected file's diff, actions, jump controls, and copy toolbar. */
|
|
12038
|
-
function PendingDiff({ file, busy, workspacePath, jumpSignal, undoFlash, failedMessage, onPasteReference, t, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen }) {
|
|
12261
|
+
function PendingDiff({ file, busy, workspacePath, jumpSignal, undoFlash, failedMessage, onPasteReference, t, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen, floatMode, floatOpen, onToggleFileList }) {
|
|
12039
12262
|
const [langOverride, setLangOverride] = (0, react.useState)(void 0);
|
|
12040
12263
|
const [langMenuOpen, setLangMenuOpen] = (0, react.useState)(false);
|
|
12041
12264
|
const langMenuItems = (0, react.useMemo)(() => [{
|
|
@@ -12048,6 +12271,17 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12048
12271
|
const detectedLang = (0, react.useMemo)(() => langFromPath(file.path), [file.path]);
|
|
12049
12272
|
const lang = (0, react.useMemo)(() => langOverride ?? detectedLang, [detectedLang, langOverride]);
|
|
12050
12273
|
const langLabel = langOverride === void 0 ? detectedLang === void 0 ? t("action.langAuto") : t("action.langAutoDetected", { lang: languageDisplayName(detectedLang) }) : languageDisplayName(langOverride);
|
|
12274
|
+
const wrapKey = lang ?? "";
|
|
12275
|
+
const [langWrap, setLangWrap] = (0, react.useState)(() => wrapEnabled(wrapKey));
|
|
12276
|
+
(0, react.useEffect)(() => {
|
|
12277
|
+
setLangWrap(wrapEnabled(wrapKey));
|
|
12278
|
+
}, [wrapKey]);
|
|
12279
|
+
const toggleLangWrap = () => {
|
|
12280
|
+
const next = !langWrap;
|
|
12281
|
+
setLangWrap(next);
|
|
12282
|
+
setWrapEnabled(wrapKey, next);
|
|
12283
|
+
};
|
|
12284
|
+
const [tabWidthSpaces] = (0, react.useState)(() => tabWidth());
|
|
12051
12285
|
const model = (0, react.useMemo)(() => {
|
|
12052
12286
|
const diff = computeWholeFileDiff(file.oldText, file.newText);
|
|
12053
12287
|
return {
|
|
@@ -12113,6 +12347,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12113
12347
|
const [scrollTick, setScrollTick] = (0, react.useState)(0);
|
|
12114
12348
|
const [scrollTop, setScrollTop] = (0, react.useState)(0);
|
|
12115
12349
|
const [viewportHeight, setViewportHeight] = (0, react.useState)(0);
|
|
12350
|
+
const [bodyWidth, setBodyWidth] = (0, react.useState)(0);
|
|
12351
|
+
const [hScrollbarPx, setHScrollbarPx] = (0, react.useState)(0);
|
|
12116
12352
|
const [hoveredBlock, setHoveredBlock] = (0, react.useState)(void 0);
|
|
12117
12353
|
const [selection, setSelection] = (0, react.useState)(void 0);
|
|
12118
12354
|
const [copied, setCopied] = (0, react.useState)(false);
|
|
@@ -12123,8 +12359,6 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12123
12359
|
const [flashKey, setFlashKey] = (0, react.useState)(0);
|
|
12124
12360
|
(0, react.useEffect)(() => {
|
|
12125
12361
|
setFocus(0);
|
|
12126
|
-
setScrollTop(0);
|
|
12127
|
-
if (bodyRef.current !== null) bodyRef.current.scrollTop = 0;
|
|
12128
12362
|
bodyRef.current?.focus();
|
|
12129
12363
|
setFlashKey((key) => key + 1);
|
|
12130
12364
|
setHoveredBlock(void 0);
|
|
@@ -12181,7 +12415,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12181
12415
|
if (row === void 0) return;
|
|
12182
12416
|
const body = bodyRef.current;
|
|
12183
12417
|
if (body === null) return;
|
|
12184
|
-
const target = row
|
|
12418
|
+
const target = offsetOf(row) + extentOf(row, row) / 2 - body.clientHeight / 2;
|
|
12185
12419
|
const clamped = Math.max(0, Math.min(target, body.scrollHeight - body.clientHeight));
|
|
12186
12420
|
if (body.scrollTop !== clamped) body.scrollTop = clamped;
|
|
12187
12421
|
setScrollTop(clamped);
|
|
@@ -12198,12 +12432,58 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12198
12432
|
}, [blockIndexByRow]);
|
|
12199
12433
|
const rows = model.diff.rows;
|
|
12200
12434
|
const rowCount = rows.length;
|
|
12201
|
-
const
|
|
12202
|
-
|
|
12203
|
-
|
|
12435
|
+
const rowWrapped = (0, react.useMemo)(() => {
|
|
12436
|
+
if (!langWrap || bodyWidth === 0) return null;
|
|
12437
|
+
const measure = makeMeasurer(codeFontOf());
|
|
12438
|
+
if (measure === void 0) return null;
|
|
12439
|
+
const charWidth = measure("0");
|
|
12440
|
+
const wrapping = bodyWidth - WRAP_GUTTERS_PX - charWidth;
|
|
12441
|
+
const tabPx = tabWidthSpaces * measure(" ");
|
|
12442
|
+
return rows.map((row) => wrapInto(row.text, wrapping, measure, tabPx));
|
|
12443
|
+
}, [
|
|
12444
|
+
langWrap,
|
|
12445
|
+
bodyWidth,
|
|
12446
|
+
rows,
|
|
12447
|
+
tabWidthSpaces
|
|
12448
|
+
]);
|
|
12449
|
+
const rowHeights = (0, react.useMemo)(() => {
|
|
12450
|
+
if (rowWrapped === null) return null;
|
|
12451
|
+
return rowWrapped.map((lines) => lines.length * ROW_HEIGHT_PX);
|
|
12452
|
+
}, [rowWrapped]);
|
|
12453
|
+
const rowOffsets = (0, react.useMemo)(() => {
|
|
12454
|
+
if (rowHeights === null) return null;
|
|
12455
|
+
const offs = new Array(rowHeights.length + 1);
|
|
12456
|
+
offs[0] = 0;
|
|
12457
|
+
for (let i = 0; i < rowHeights.length; i++) offs[i + 1] = offs[i] + rowHeights[i];
|
|
12458
|
+
return offs;
|
|
12459
|
+
}, [rowHeights]);
|
|
12460
|
+
const totalHeight = rowOffsets === null ? rowCount * ROW_HEIGHT_PX : rowOffsets[rowCount] ?? 0;
|
|
12461
|
+
const offsetOf = (index) => {
|
|
12462
|
+
if (rowOffsets === null) return index * ROW_HEIGHT_PX;
|
|
12463
|
+
return rowOffsets[Math.max(0, Math.min(index, rowCount))] ?? 0;
|
|
12464
|
+
};
|
|
12465
|
+
const extentOf = (from, to) => {
|
|
12466
|
+
if (rowOffsets === null) return (to - from + 1) * ROW_HEIGHT_PX;
|
|
12467
|
+
return Math.max(0, offsetOf(to + 1) - offsetOf(from));
|
|
12468
|
+
};
|
|
12469
|
+
const rowAtY = (y) => {
|
|
12470
|
+
if (rowOffsets === null) return Math.floor(y / ROW_HEIGHT_PX);
|
|
12471
|
+
if (y <= 0) return 0;
|
|
12472
|
+
let lo = 0;
|
|
12473
|
+
let hi = rowCount;
|
|
12474
|
+
while (lo < hi) {
|
|
12475
|
+
const mid = lo + hi + 1 >> 1;
|
|
12476
|
+
if (rowOffsets[mid] <= y) lo = mid;
|
|
12477
|
+
else hi = mid - 1;
|
|
12478
|
+
}
|
|
12479
|
+
return lo;
|
|
12480
|
+
};
|
|
12481
|
+
const viewport = viewportHeight > 0 ? viewportHeight : totalHeight;
|
|
12482
|
+
const start = Math.max(0, rowAtY(scrollTop) - OVERSCAN_ROWS);
|
|
12483
|
+
const end = Math.min(rowCount, rowAtY(scrollTop + viewport) + OVERSCAN_ROWS);
|
|
12204
12484
|
const visibleRows = rows.slice(start, end);
|
|
12205
|
-
const
|
|
12206
|
-
const
|
|
12485
|
+
const blockEnd = hoveredBlock === void 0 ? void 0 : model.blocks[hoveredBlock]?.end;
|
|
12486
|
+
const blockActionsTop = blockEnd === void 0 ? 0 : Math.min(offsetOf(blockEnd + 1), Math.max(0, totalHeight - BLOCK_ACTIONS_FRAME_PX));
|
|
12207
12487
|
const widestLine = (0, react.useMemo)(() => {
|
|
12208
12488
|
let widest = 0;
|
|
12209
12489
|
for (const row of model.diff.rows) if (row.text.length > widest) widest = row.text.length;
|
|
@@ -12222,13 +12502,27 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12222
12502
|
observer?.disconnect();
|
|
12223
12503
|
};
|
|
12224
12504
|
}, [file.id]);
|
|
12505
|
+
(0, react.useEffect)(() => {
|
|
12506
|
+
const body = bodyRef.current;
|
|
12507
|
+
if (body === null) return;
|
|
12508
|
+
const measure = () => {
|
|
12509
|
+
setBodyWidth(body.clientWidth);
|
|
12510
|
+
setHScrollbarPx(Math.max(0, body.offsetHeight - body.clientHeight));
|
|
12511
|
+
};
|
|
12512
|
+
measure();
|
|
12513
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
|
|
12514
|
+
observer?.observe(body);
|
|
12515
|
+
return () => {
|
|
12516
|
+
observer?.disconnect();
|
|
12517
|
+
};
|
|
12518
|
+
}, [file.id, langWrap]);
|
|
12225
12519
|
(0, react.useLayoutEffect)(() => {
|
|
12226
12520
|
if (rowCount === 0) return;
|
|
12227
12521
|
const block = model.blocks[focus];
|
|
12228
12522
|
if (block === void 0) return;
|
|
12229
12523
|
const body = bodyRef.current;
|
|
12230
12524
|
if (body === null) return;
|
|
12231
|
-
const target = block.start
|
|
12525
|
+
const target = offsetOf(block.start) - 44;
|
|
12232
12526
|
const clamped = Math.max(0, Math.min(target, body.scrollHeight - body.clientHeight));
|
|
12233
12527
|
if (body.scrollTop !== clamped) body.scrollTop = clamped;
|
|
12234
12528
|
setScrollTop(clamped);
|
|
@@ -12236,7 +12530,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12236
12530
|
model,
|
|
12237
12531
|
focus,
|
|
12238
12532
|
scrollTick,
|
|
12239
|
-
rowCount
|
|
12533
|
+
rowCount,
|
|
12534
|
+
rowOffsets === null
|
|
12240
12535
|
]);
|
|
12241
12536
|
const jump = (direction) => {
|
|
12242
12537
|
if (rowCount === 0) return;
|
|
@@ -12246,13 +12541,22 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12246
12541
|
for (let index = current + 1; index < model.blocks.length; index++) {
|
|
12247
12542
|
const block = model.blocks[index];
|
|
12248
12543
|
if (block === void 0) continue;
|
|
12249
|
-
if (block.start
|
|
12544
|
+
if (offsetOf(block.start) >= top) return index;
|
|
12250
12545
|
}
|
|
12251
12546
|
return 0;
|
|
12252
12547
|
});
|
|
12253
12548
|
setScrollTick((tick) => tick + 1);
|
|
12254
12549
|
setFlashKey((key) => key + 1);
|
|
12255
12550
|
};
|
|
12551
|
+
const stepBlock = (direction) => {
|
|
12552
|
+
const count = model.blocks.length;
|
|
12553
|
+
if (count === 0) return;
|
|
12554
|
+
const target = ((hoveredBlock ?? focus) + direction + count) % count;
|
|
12555
|
+
setHoveredBlock(target);
|
|
12556
|
+
setFocus(target);
|
|
12557
|
+
setScrollTick((tick) => tick + 1);
|
|
12558
|
+
setFlashKey((key) => key + 1);
|
|
12559
|
+
};
|
|
12256
12560
|
(0, react.useEffect)(() => {
|
|
12257
12561
|
if (jumpSignal === 0) return;
|
|
12258
12562
|
jump(1);
|
|
@@ -12342,6 +12646,9 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12342
12646
|
const scrollbarWidth = scroller.offsetWidth - scroller.clientWidth;
|
|
12343
12647
|
return Math.max(0, scroller.clientWidth - (scrollbarWidth > 0 ? 0 : OVERVIEW_RULER_WIDTH_PX));
|
|
12344
12648
|
})();
|
|
12649
|
+
const flashTop = focusedBlock === void 0 ? 0 : Math.max(0, offsetOf(focusedBlock.start) - scrollTop);
|
|
12650
|
+
const flashBottom = focusedBlock === void 0 ? 0 : Math.min(viewportHeight > 0 ? viewportHeight : Number.POSITIVE_INFINITY, offsetOf(focusedBlock.end + 1) - scrollTop);
|
|
12651
|
+
const flashHeight = Math.max(0, flashBottom - flashTop);
|
|
12345
12652
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
12346
12653
|
className: PendingPanel_module_css_default.diff,
|
|
12347
12654
|
"data-diff-approval-diff": true,
|
|
@@ -12388,6 +12695,19 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12388
12695
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
12389
12696
|
className: PendingPanel_module_css_default.diffActions,
|
|
12390
12697
|
children: [
|
|
12698
|
+
floatMode && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
12699
|
+
label: t(floatOpen ? "action.hideFileList" : "action.showFileList"),
|
|
12700
|
+
side: "bottom",
|
|
12701
|
+
delayMs: 500,
|
|
12702
|
+
children: (0, react_jsx_runtime.jsx)("button", {
|
|
12703
|
+
type: "button",
|
|
12704
|
+
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.iconAction}`,
|
|
12705
|
+
"data-diff-file-list-toggle": true,
|
|
12706
|
+
"aria-label": t(floatOpen ? "action.hideFileList" : "action.showFileList"),
|
|
12707
|
+
onClick: onToggleFileList,
|
|
12708
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconListPenOutline16, { size: 14 })
|
|
12709
|
+
})
|
|
12710
|
+
}),
|
|
12391
12711
|
(0, react_jsx_runtime.jsx)("span", {
|
|
12392
12712
|
className: PendingPanel_module_css_default.diffStats,
|
|
12393
12713
|
children: t("panel.stats", {
|
|
@@ -12400,7 +12720,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12400
12720
|
children: t("panel.createHint")
|
|
12401
12721
|
}),
|
|
12402
12722
|
model.blocks.length > 0 && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
12403
|
-
label: t("action.prevDiff")
|
|
12723
|
+
label: `${t("action.prevDiff")} (Ctrl+↑)`,
|
|
12404
12724
|
side: "bottom",
|
|
12405
12725
|
delayMs: 500,
|
|
12406
12726
|
children: (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -12415,7 +12735,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12415
12735
|
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, { size: 14 })
|
|
12416
12736
|
})
|
|
12417
12737
|
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
12418
|
-
label: t("action.nextDiff")
|
|
12738
|
+
label: `${t("action.nextDiff")} (Ctrl+↓)`,
|
|
12419
12739
|
side: "bottom",
|
|
12420
12740
|
delayMs: 500,
|
|
12421
12741
|
children: (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -12486,14 +12806,18 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12486
12806
|
onMouseLeave: () => {
|
|
12487
12807
|
setHoveredBlock(void 0);
|
|
12488
12808
|
},
|
|
12809
|
+
style: { tabSize: tabWidthSpaces },
|
|
12489
12810
|
"data-diff-body": true,
|
|
12490
12811
|
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
12491
|
-
className: PendingPanel_module_css_default.lines
|
|
12492
|
-
style:
|
|
12812
|
+
className: `${PendingPanel_module_css_default.lines}${langWrap ? " " + PendingPanel_module_css_default.wrap : ""}`,
|
|
12813
|
+
style: langWrap ? {
|
|
12814
|
+
width: "100%",
|
|
12815
|
+
minWidth: "100%"
|
|
12816
|
+
} : { minWidth: `max(100%, ${widestLine}ch)` },
|
|
12493
12817
|
children: [
|
|
12494
12818
|
start > 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
12495
12819
|
className: PendingPanel_module_css_default.vSpacer,
|
|
12496
|
-
style: { height: start
|
|
12820
|
+
style: { height: offsetOf(start) },
|
|
12497
12821
|
"aria-hidden": "true"
|
|
12498
12822
|
}),
|
|
12499
12823
|
visibleRows.map((row, offset) => {
|
|
@@ -12505,24 +12829,20 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12505
12829
|
focused: inFocusedBlock(index),
|
|
12506
12830
|
searchHit: searchHitSet.has(index),
|
|
12507
12831
|
searchCurrent: index === currentSearchRow,
|
|
12508
|
-
onRowHover
|
|
12832
|
+
onRowHover,
|
|
12833
|
+
wrappedLines: rowWrapped?.[index]
|
|
12509
12834
|
}, index);
|
|
12510
12835
|
}),
|
|
12511
12836
|
end < rowCount && (0, react_jsx_runtime.jsx)("div", {
|
|
12512
12837
|
className: PendingPanel_module_css_default.vSpacer,
|
|
12513
|
-
style: { height:
|
|
12514
|
-
"aria-hidden": "true"
|
|
12515
|
-
}),
|
|
12516
|
-
blockActionsPadPx > 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
12517
|
-
className: PendingPanel_module_css_default.vSpacer,
|
|
12518
|
-
style: { height: blockActionsPadPx },
|
|
12838
|
+
style: { height: totalHeight - offsetOf(end) },
|
|
12519
12839
|
"aria-hidden": "true"
|
|
12520
12840
|
})
|
|
12521
12841
|
]
|
|
12522
12842
|
}), hoveredBlock !== void 0 && model.blocks[hoveredBlock] !== void 0 && (0, react_jsx_runtime.jsxs)("div", {
|
|
12523
12843
|
className: PendingPanel_module_css_default.blockActions,
|
|
12524
12844
|
"data-diff-block-actions": true,
|
|
12525
|
-
style: { top:
|
|
12845
|
+
style: { top: blockActionsTop },
|
|
12526
12846
|
children: [
|
|
12527
12847
|
(0, react_jsx_runtime.jsx)("span", {
|
|
12528
12848
|
className: PendingPanel_module_css_default.blockPosition,
|
|
@@ -12532,6 +12852,28 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12532
12852
|
total: model.blocks.length
|
|
12533
12853
|
})
|
|
12534
12854
|
}),
|
|
12855
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
12856
|
+
type: "button",
|
|
12857
|
+
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.iconAction}`,
|
|
12858
|
+
"data-diff-block-prev": true,
|
|
12859
|
+
"aria-label": t("action.prevDiff"),
|
|
12860
|
+
disabled: busy,
|
|
12861
|
+
onClick: () => {
|
|
12862
|
+
stepBlock(-1);
|
|
12863
|
+
},
|
|
12864
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, { size: 14 })
|
|
12865
|
+
}),
|
|
12866
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
12867
|
+
type: "button",
|
|
12868
|
+
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.iconAction}`,
|
|
12869
|
+
"data-diff-block-next": true,
|
|
12870
|
+
"aria-label": t("action.nextDiff"),
|
|
12871
|
+
disabled: busy,
|
|
12872
|
+
onClick: () => {
|
|
12873
|
+
stepBlock(1);
|
|
12874
|
+
},
|
|
12875
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 })
|
|
12876
|
+
}),
|
|
12535
12877
|
(0, react_jsx_runtime.jsx)("button", {
|
|
12536
12878
|
type: "button",
|
|
12537
12879
|
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.actionPrimary}`,
|
|
@@ -12559,8 +12901,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12559
12901
|
className: PendingPanel_module_css_default.blockFlash,
|
|
12560
12902
|
"data-diff-block-flash": true,
|
|
12561
12903
|
style: {
|
|
12562
|
-
top:
|
|
12563
|
-
height:
|
|
12904
|
+
top: flashTop,
|
|
12905
|
+
height: flashHeight,
|
|
12564
12906
|
width: flashWidth
|
|
12565
12907
|
}
|
|
12566
12908
|
}, flashKey),
|
|
@@ -12625,6 +12967,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12625
12967
|
className: PendingPanel_module_css_default.overviewRuler,
|
|
12626
12968
|
"data-diff-approval-ruler": true,
|
|
12627
12969
|
"aria-hidden": "true",
|
|
12970
|
+
style: { bottom: hScrollbarPx },
|
|
12628
12971
|
children: rulerMarkers.map((marker, index) => (0, react_jsx_runtime.jsx)("div", {
|
|
12629
12972
|
className: `${PendingPanel_module_css_default.overviewMarker} ${marker.kind === "del" ? PendingPanel_module_css_default.markerDel : PendingPanel_module_css_default.markerAdd}`,
|
|
12630
12973
|
"data-diff-ruler-marker": marker.kind,
|
|
@@ -12690,6 +13033,23 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12690
13033
|
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 12 })]
|
|
12691
13034
|
})
|
|
12692
13035
|
})
|
|
13036
|
+
}),
|
|
13037
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
13038
|
+
label: langWrap ? t("action.toggleOff") : t("action.toggleOn"),
|
|
13039
|
+
side: "top",
|
|
13040
|
+
delayMs: 500,
|
|
13041
|
+
children: (0, react_jsx_runtime.jsx)("button", {
|
|
13042
|
+
type: "button",
|
|
13043
|
+
className: `${PendingPanel_module_css_default.langSelect}${langWrap ? " " + PendingPanel_module_css_default.wrapActive : ""}`,
|
|
13044
|
+
"data-diff-wrap": true,
|
|
13045
|
+
"aria-label": langWrap ? t("action.toggleOff") : t("action.toggleOn"),
|
|
13046
|
+
"aria-pressed": langWrap,
|
|
13047
|
+
onClick: toggleLangWrap,
|
|
13048
|
+
children: (0, react_jsx_runtime.jsx)("span", {
|
|
13049
|
+
className: PendingPanel_module_css_default.langLabel,
|
|
13050
|
+
children: t("action.wrap")
|
|
13051
|
+
})
|
|
13052
|
+
})
|
|
12693
13053
|
})
|
|
12694
13054
|
]
|
|
12695
13055
|
})
|
|
@@ -12697,7 +13057,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12697
13057
|
});
|
|
12698
13058
|
}
|
|
12699
13059
|
/** Render the pending-edit review panel and its unified footer action. */
|
|
12700
|
-
function PendingPanel({ wide, useSessions, usePending, onRefresh, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen, onPasteReference, onUndo, onRedo, onImportVcs, t }) {
|
|
13060
|
+
function PendingPanel({ wide, useSessions, usePending, onRefresh, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen, onPasteReference, onUndo, onRedo, onImportVcs, onAckRedoCleared, t }) {
|
|
12701
13061
|
const current = useSessions((state) => state.current);
|
|
12702
13062
|
const currentBlank = useSessions((state) => {
|
|
12703
13063
|
const id = state.current;
|
|
@@ -12725,8 +13085,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12725
13085
|
const [importToast, setImportToast] = (0, react.useState)(null);
|
|
12726
13086
|
/** A transient banner for a keep/revert failure. */
|
|
12727
13087
|
const [actionToast, setActionToast] = (0, react.useState)(null);
|
|
12728
|
-
/**
|
|
12729
|
-
const [
|
|
13088
|
+
/** Whether the redo-cleared notice is showing (bottom-right, OK to dismiss). */
|
|
13089
|
+
const [redoClearedNotice, setRedoClearedNotice] = (0, react.useState)(false);
|
|
12730
13090
|
/** Bottom offset tracking the chat composer's top edge so the input stays visible. */
|
|
12731
13091
|
const [bottomPx, setBottomPx] = (0, react.useState)(FALLBACK_BOTTOM_PX);
|
|
12732
13092
|
/** Fullscreen expanded: the panel bottom pins to the window edge, ignoring the composer offset. */
|
|
@@ -12734,6 +13094,16 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12734
13094
|
/** File-list pane width, adjustable by dragging the divider. */
|
|
12735
13095
|
const [listWidth, setListWidth] = (0, react.useState)(240);
|
|
12736
13096
|
const resizeDrag = (0, react.useRef)(null);
|
|
13097
|
+
/** Whether the floating (collapsed) file list is currently expanded. */
|
|
13098
|
+
const [floatOpen, setFloatOpen] = (0, react.useState)(false);
|
|
13099
|
+
/** The review panel's width, measured so the file list can collapse when it
|
|
13100
|
+
* would take more than a third of it (browser zoom / window resize). */
|
|
13101
|
+
const [panelWidth, setPanelWidth] = (0, react.useState)(0);
|
|
13102
|
+
const panelRef = (0, react.useRef)(null);
|
|
13103
|
+
const splitRef = (0, react.useRef)(null);
|
|
13104
|
+
/** The code scroll box's bounds within the split, so the floating card is
|
|
13105
|
+
* constrained to it. */
|
|
13106
|
+
const [floatBox, setFloatBox] = (0, react.useState)(null);
|
|
12737
13107
|
(0, react.useEffect)(() => {
|
|
12738
13108
|
onRefresh(current);
|
|
12739
13109
|
const timer = setInterval(() => {
|
|
@@ -12743,6 +13113,64 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12743
13113
|
clearInterval(timer);
|
|
12744
13114
|
};
|
|
12745
13115
|
}, [current, onRefresh]);
|
|
13116
|
+
(0, react.useEffect)(() => {
|
|
13117
|
+
const el = panelRef.current;
|
|
13118
|
+
if (el === null) return;
|
|
13119
|
+
const measure = () => {
|
|
13120
|
+
setPanelWidth(el.clientWidth);
|
|
13121
|
+
};
|
|
13122
|
+
measure();
|
|
13123
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
|
|
13124
|
+
observer?.observe(el);
|
|
13125
|
+
return () => {
|
|
13126
|
+
observer?.disconnect();
|
|
13127
|
+
};
|
|
13128
|
+
}, [open]);
|
|
13129
|
+
const floatMode = panelWidth > 0 && listWidth > panelWidth / 3;
|
|
13130
|
+
const toggleFileList = () => {
|
|
13131
|
+
setFloatOpen((value) => !value);
|
|
13132
|
+
};
|
|
13133
|
+
(0, react.useEffect)(() => {
|
|
13134
|
+
if (!floatMode || !floatOpen) return;
|
|
13135
|
+
const el = panelRef.current;
|
|
13136
|
+
if (el === null) return;
|
|
13137
|
+
const onPointerDown = (event) => {
|
|
13138
|
+
const target = event.target;
|
|
13139
|
+
if (target instanceof Element && (target.closest("[data-diff-floating-file-list]") !== null || target.closest("[data-diff-file-list-toggle]") !== null)) return;
|
|
13140
|
+
setFloatOpen(false);
|
|
13141
|
+
};
|
|
13142
|
+
el.addEventListener("pointerdown", onPointerDown, true);
|
|
13143
|
+
return () => {
|
|
13144
|
+
el.removeEventListener("pointerdown", onPointerDown, true);
|
|
13145
|
+
};
|
|
13146
|
+
}, [floatMode, floatOpen]);
|
|
13147
|
+
(0, react.useEffect)(() => {
|
|
13148
|
+
if (!floatMode || !floatOpen) return;
|
|
13149
|
+
const split = splitRef.current;
|
|
13150
|
+
const body = panelRef.current?.querySelector("[data-diff-body]");
|
|
13151
|
+
if (split === null || body == null) return;
|
|
13152
|
+
const s = split.getBoundingClientRect();
|
|
13153
|
+
const b = body.getBoundingClientRect();
|
|
13154
|
+
setFloatBox({
|
|
13155
|
+
left: b.left - s.left,
|
|
13156
|
+
top: b.top - s.top,
|
|
13157
|
+
width: b.width,
|
|
13158
|
+
height: b.height
|
|
13159
|
+
});
|
|
13160
|
+
}, [
|
|
13161
|
+
floatMode,
|
|
13162
|
+
floatOpen,
|
|
13163
|
+
panelWidth
|
|
13164
|
+
]);
|
|
13165
|
+
(0, react.useEffect)(() => {
|
|
13166
|
+
if (!open || !snapshot.redoCleared) return;
|
|
13167
|
+
onAckRedoCleared();
|
|
13168
|
+
setRedoClearedNotice(true);
|
|
13169
|
+
}, [
|
|
13170
|
+
open,
|
|
13171
|
+
snapshot.redoCleared,
|
|
13172
|
+
onAckRedoCleared
|
|
13173
|
+
]);
|
|
12746
13174
|
(0, react.useEffect)(() => {
|
|
12747
13175
|
if (!open) return;
|
|
12748
13176
|
const MEASURE_INTERVAL_MS = 400;
|
|
@@ -12786,7 +13214,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12786
13214
|
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
12787
13215
|
};
|
|
12788
13216
|
}, [open]);
|
|
12789
|
-
const files = snapshot.files.filter((file) => file.sessionId === current);
|
|
13217
|
+
const files = snapshot.files.filter((file) => file.sessionId === current).sort((left, right) => compareFileNames(left.path, right.path));
|
|
12790
13218
|
/** Per-file keep/revert failures, surfaced inline on the row and detail. */
|
|
12791
13219
|
const failed = snapshot.failed ?? EMPTY_FAILED_MAP;
|
|
12792
13220
|
const failedInitialized = (0, react.useRef)(false);
|
|
@@ -12814,23 +13242,6 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12814
13242
|
files,
|
|
12815
13243
|
selected
|
|
12816
13244
|
]);
|
|
12817
|
-
(0, react.useEffect)(() => {
|
|
12818
|
-
if (!open || openedCount === 0) return;
|
|
12819
|
-
if (!(snapshot.read && snapshot.error === void 0 && files.length === 0)) return;
|
|
12820
|
-
const timer = window.setTimeout(() => {
|
|
12821
|
-
setOpenedCount(0);
|
|
12822
|
-
setOpen(false);
|
|
12823
|
-
}, EMPTY_CLOSE_GRACE_MS);
|
|
12824
|
-
return () => {
|
|
12825
|
-
window.clearTimeout(timer);
|
|
12826
|
-
};
|
|
12827
|
-
}, [
|
|
12828
|
-
open,
|
|
12829
|
-
openedCount,
|
|
12830
|
-
snapshot.read,
|
|
12831
|
-
snapshot.error,
|
|
12832
|
-
files.length
|
|
12833
|
-
]);
|
|
12834
13245
|
const runImportVcs = async () => {
|
|
12835
13246
|
if (current === void 0 || importBusy) return;
|
|
12836
13247
|
setImportBusy(true);
|
|
@@ -12850,7 +13261,6 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12850
13261
|
}
|
|
12851
13262
|
};
|
|
12852
13263
|
const toggleOpen = () => {
|
|
12853
|
-
if (!open) setOpenedCount(files.length);
|
|
12854
13264
|
setOpen((value) => !value);
|
|
12855
13265
|
};
|
|
12856
13266
|
(0, react.useEffect)(() => {
|
|
@@ -12877,6 +13287,37 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12877
13287
|
}
|
|
12878
13288
|
}, entry.id);
|
|
12879
13289
|
const selectedFile = files.find((file) => file.id === selected);
|
|
13290
|
+
const fileListBody = (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("div", {
|
|
13291
|
+
className: PendingPanel_module_css_default.listScroll,
|
|
13292
|
+
children: files.length > 0 && (0, react_jsx_runtime.jsxs)("section", { children: [(0, react_jsx_runtime.jsx)("h3", {
|
|
13293
|
+
className: PendingPanel_module_css_default.group,
|
|
13294
|
+
children: t("panel.group.current")
|
|
13295
|
+
}), (0, react_jsx_runtime.jsx)("ul", {
|
|
13296
|
+
className: PendingPanel_module_css_default.rows,
|
|
13297
|
+
children: files.map(renderEntry)
|
|
13298
|
+
})] })
|
|
13299
|
+
}), files.length > 0 && (0, react_jsx_runtime.jsxs)("div", {
|
|
13300
|
+
className: PendingPanel_module_css_default.bulkActions,
|
|
13301
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
13302
|
+
type: "button",
|
|
13303
|
+
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.actionPrimary}`,
|
|
13304
|
+
"data-diff-keep-all": true,
|
|
13305
|
+
disabled: bulkBusy !== null,
|
|
13306
|
+
onClick: () => {
|
|
13307
|
+
runBulk("keep");
|
|
13308
|
+
},
|
|
13309
|
+
children: bulkBusy === "keep" ? t("action.busy") : t("action.keepAll")
|
|
13310
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
13311
|
+
type: "button",
|
|
13312
|
+
className: PendingPanel_module_css_default.action,
|
|
13313
|
+
"data-diff-revert-all": true,
|
|
13314
|
+
disabled: bulkBusy !== null,
|
|
13315
|
+
onClick: () => {
|
|
13316
|
+
runBulk("revert");
|
|
13317
|
+
},
|
|
13318
|
+
children: bulkBusy === "revert" ? t("action.busy") : t("action.revertAll")
|
|
13319
|
+
})]
|
|
13320
|
+
})] });
|
|
12880
13321
|
const handleUndo = async (sessionId) => {
|
|
12881
13322
|
const id = await onUndo(sessionId);
|
|
12882
13323
|
if (id === void 0) return;
|
|
@@ -12960,6 +13401,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12960
13401
|
}),
|
|
12961
13402
|
open && (0, react_jsx_runtime.jsxs)("section", {
|
|
12962
13403
|
className: PendingPanel_module_css_default.panel,
|
|
13404
|
+
ref: panelRef,
|
|
12963
13405
|
style: { bottom: expanded ? PANEL_INSET_PX : bottomPx },
|
|
12964
13406
|
"data-diff-approval-panel": true,
|
|
12965
13407
|
"aria-label": t("panel.title"),
|
|
@@ -13058,44 +13500,15 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13058
13500
|
]
|
|
13059
13501
|
}) : (0, react_jsx_runtime.jsxs)("div", {
|
|
13060
13502
|
className: PendingPanel_module_css_default.split,
|
|
13503
|
+
ref: splitRef,
|
|
13061
13504
|
children: [
|
|
13062
|
-
(0, react_jsx_runtime.
|
|
13505
|
+
!floatMode && (0, react_jsx_runtime.jsx)("nav", {
|
|
13063
13506
|
className: PendingPanel_module_css_default.fileList,
|
|
13064
13507
|
style: { width: listWidth },
|
|
13065
13508
|
"data-diff-approval-file-list": true,
|
|
13066
|
-
children:
|
|
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
|
-
})]
|
|
13509
|
+
children: fileListBody
|
|
13097
13510
|
}),
|
|
13098
|
-
(0, react_jsx_runtime.jsx)("div", {
|
|
13511
|
+
!floatMode && (0, react_jsx_runtime.jsx)("div", {
|
|
13099
13512
|
className: PendingPanel_module_css_default.resizeHandle,
|
|
13100
13513
|
"data-diff-resize": true,
|
|
13101
13514
|
onMouseDown: startResize
|
|
@@ -13118,8 +13531,22 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13118
13531
|
onRevert,
|
|
13119
13532
|
onBlockKeep,
|
|
13120
13533
|
onBlockRevert,
|
|
13121
|
-
onOpen
|
|
13534
|
+
onOpen,
|
|
13535
|
+
floatMode,
|
|
13536
|
+
floatOpen,
|
|
13537
|
+
onToggleFileList: toggleFileList
|
|
13122
13538
|
})
|
|
13539
|
+
}),
|
|
13540
|
+
floatMode && floatOpen && files.length > 0 && floatBox !== null && (0, react_jsx_runtime.jsx)("div", {
|
|
13541
|
+
className: PendingPanel_module_css_default.fileListFloat,
|
|
13542
|
+
style: {
|
|
13543
|
+
left: floatBox.left + FLOAT_LIST_MARGIN_PX,
|
|
13544
|
+
top: floatBox.top + FLOAT_LIST_MARGIN_PX,
|
|
13545
|
+
width: Math.min(listWidth, Math.max(0, floatBox.width - 24)),
|
|
13546
|
+
height: Math.max(0, floatBox.height - 24)
|
|
13547
|
+
},
|
|
13548
|
+
"data-diff-floating-file-list": true,
|
|
13549
|
+
children: fileListBody
|
|
13123
13550
|
})
|
|
13124
13551
|
]
|
|
13125
13552
|
})]
|
|
@@ -13147,6 +13574,23 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13147
13574
|
})
|
|
13148
13575
|
]
|
|
13149
13576
|
})
|
|
13577
|
+
}),
|
|
13578
|
+
redoClearedNotice && (0, react_jsx_runtime.jsxs)("div", {
|
|
13579
|
+
className: PendingPanel_module_css_default.notice,
|
|
13580
|
+
role: "status",
|
|
13581
|
+
"data-diff-approval-notice": true,
|
|
13582
|
+
children: [(0, react_jsx_runtime.jsx)("p", {
|
|
13583
|
+
className: PendingPanel_module_css_default.noticeText,
|
|
13584
|
+
children: t("panel.externalChanged")
|
|
13585
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
13586
|
+
type: "button",
|
|
13587
|
+
className: PendingPanel_module_css_default.noticeButton,
|
|
13588
|
+
"data-diff-notice-dismiss": true,
|
|
13589
|
+
onClick: () => {
|
|
13590
|
+
setRedoClearedNotice(false);
|
|
13591
|
+
},
|
|
13592
|
+
children: t("panel.dismiss")
|
|
13593
|
+
})]
|
|
13150
13594
|
})
|
|
13151
13595
|
]
|
|
13152
13596
|
});
|
|
@@ -13211,17 +13655,78 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13211
13655
|
})]
|
|
13212
13656
|
});
|
|
13213
13657
|
}
|
|
13658
|
+
/** A picker offering the tab-width choices 2 / 4 / 8 (spaces). */
|
|
13659
|
+
function TabWidthPicker({ value, open, onOpenChange, onSelect, dataAttribute }) {
|
|
13660
|
+
return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
13661
|
+
open,
|
|
13662
|
+
onClose: () => {
|
|
13663
|
+
onOpenChange(false);
|
|
13664
|
+
},
|
|
13665
|
+
items: [
|
|
13666
|
+
2,
|
|
13667
|
+
4,
|
|
13668
|
+
8
|
|
13669
|
+
].map((n) => ({
|
|
13670
|
+
id: String(n),
|
|
13671
|
+
label: String(n)
|
|
13672
|
+
})),
|
|
13673
|
+
selectedId: String(value),
|
|
13674
|
+
onSelect: (id) => {
|
|
13675
|
+
onOpenChange(false);
|
|
13676
|
+
const n = Number.parseInt(id, 10);
|
|
13677
|
+
if (Number.isFinite(n)) onSelect(n);
|
|
13678
|
+
},
|
|
13679
|
+
align: "end",
|
|
13680
|
+
portal: true,
|
|
13681
|
+
anchor: (0, react_jsx_runtime.jsxs)("button", {
|
|
13682
|
+
type: "button",
|
|
13683
|
+
className: PendingPanel_module_css_default.settingsSelector,
|
|
13684
|
+
"aria-haspopup": "menu",
|
|
13685
|
+
"aria-expanded": open,
|
|
13686
|
+
onClick: () => {
|
|
13687
|
+
onOpenChange(!open);
|
|
13688
|
+
},
|
|
13689
|
+
[dataAttribute]: true,
|
|
13690
|
+
children: [value, (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: PendingPanel_module_css_default.settingsSelectorChevron })]
|
|
13691
|
+
})
|
|
13692
|
+
});
|
|
13693
|
+
}
|
|
13694
|
+
/** One tab-width preference row: title + description, number picker right. */
|
|
13695
|
+
function TabWidthRow({ title, description, value, open, onOpenChange, onSelect, dataAttribute }) {
|
|
13696
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
13697
|
+
className: PendingPanel_module_css_default.settingsRow,
|
|
13698
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
13699
|
+
className: PendingPanel_module_css_default.settingsRowText,
|
|
13700
|
+
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
13701
|
+
className: PendingPanel_module_css_default.settingsRowTitle,
|
|
13702
|
+
children: title
|
|
13703
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
13704
|
+
className: PendingPanel_module_css_default.settingsRowDesc,
|
|
13705
|
+
children: description
|
|
13706
|
+
})]
|
|
13707
|
+
}), (0, react_jsx_runtime.jsx)(TabWidthPicker, {
|
|
13708
|
+
value,
|
|
13709
|
+
open,
|
|
13710
|
+
onOpenChange,
|
|
13711
|
+
onSelect,
|
|
13712
|
+
dataAttribute
|
|
13713
|
+
})]
|
|
13714
|
+
});
|
|
13715
|
+
}
|
|
13214
13716
|
/**
|
|
13215
|
-
* The plugin's preferences: auto-paste a copied reference into the input,
|
|
13216
|
-
* whether importing workspace VCS changes includes untracked files
|
|
13217
|
-
* mirrors the harness's Agent-preset row (title +
|
|
13218
|
-
* pill picker on the right)
|
|
13717
|
+
* The plugin's preferences: auto-paste a copied reference into the input,
|
|
13718
|
+
* whether importing workspace VCS changes includes untracked files, and the
|
|
13719
|
+
* diff's tab width. Each row mirrors the harness's Agent-preset row (title +
|
|
13720
|
+
* description on the left, a pill picker on the right); the tab-width row
|
|
13721
|
+
* offers 2 / 4 / 8 spaces.
|
|
13219
13722
|
*/
|
|
13220
13723
|
function DiffApprovalSettingsTab({ t }) {
|
|
13221
13724
|
const [pasteOnCopy, setPasteOnCopyState] = (0, react.useState)(pasteOnCopyEnabled);
|
|
13222
13725
|
const [pasteOnCopyOpen, setPasteOnCopyOpen] = (0, react.useState)(false);
|
|
13223
13726
|
const [includeUntracked, setIncludeUntrackedState] = (0, react.useState)(includeUntrackedEnabled);
|
|
13224
13727
|
const [includeUntrackedOpen, setIncludeUntrackedOpen] = (0, react.useState)(false);
|
|
13728
|
+
const [tab, setTabState] = (0, react.useState)(tabWidth);
|
|
13729
|
+
const [tabOpen, setTabOpen] = (0, react.useState)(false);
|
|
13225
13730
|
const setPasteOnCopy = (value) => {
|
|
13226
13731
|
setPasteOnCopyState(value);
|
|
13227
13732
|
setPasteOnCopyEnabled(value);
|
|
@@ -13230,28 +13735,44 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13230
13735
|
setIncludeUntrackedState(value);
|
|
13231
13736
|
setIncludeUntrackedEnabled(value);
|
|
13232
13737
|
};
|
|
13738
|
+
const setTab = (value) => {
|
|
13739
|
+
setTabState(value);
|
|
13740
|
+
setTabWidth(value);
|
|
13741
|
+
};
|
|
13233
13742
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
13234
13743
|
className: PendingPanel_module_css_default.settingsPage,
|
|
13235
13744
|
"data-diff-settings": true,
|
|
13236
|
-
children: [
|
|
13237
|
-
|
|
13238
|
-
|
|
13239
|
-
|
|
13240
|
-
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
13246
|
-
|
|
13247
|
-
|
|
13248
|
-
|
|
13249
|
-
|
|
13250
|
-
|
|
13251
|
-
|
|
13252
|
-
|
|
13253
|
-
|
|
13254
|
-
|
|
13745
|
+
children: [
|
|
13746
|
+
(0, react_jsx_runtime.jsx)(PreferenceRow, {
|
|
13747
|
+
title: t("panel.pasteOnCopy"),
|
|
13748
|
+
description: t("panel.pasteOnCopyDesc"),
|
|
13749
|
+
value: pasteOnCopy,
|
|
13750
|
+
open: pasteOnCopyOpen,
|
|
13751
|
+
onOpenChange: setPasteOnCopyOpen,
|
|
13752
|
+
onSelect: setPasteOnCopy,
|
|
13753
|
+
dataAttribute: "data-diff-paste-on-copy-select",
|
|
13754
|
+
t
|
|
13755
|
+
}),
|
|
13756
|
+
(0, react_jsx_runtime.jsx)(PreferenceRow, {
|
|
13757
|
+
title: t("panel.importUntracked"),
|
|
13758
|
+
description: t("panel.importUntrackedDesc"),
|
|
13759
|
+
value: includeUntracked,
|
|
13760
|
+
open: includeUntrackedOpen,
|
|
13761
|
+
onOpenChange: setIncludeUntrackedOpen,
|
|
13762
|
+
onSelect: setIncludeUntracked,
|
|
13763
|
+
dataAttribute: "data-diff-import-untracked-select",
|
|
13764
|
+
t
|
|
13765
|
+
}),
|
|
13766
|
+
(0, react_jsx_runtime.jsx)(TabWidthRow, {
|
|
13767
|
+
title: t("panel.tabWidth"),
|
|
13768
|
+
description: t("panel.tabWidthDesc"),
|
|
13769
|
+
value: tab,
|
|
13770
|
+
open: tabOpen,
|
|
13771
|
+
onOpenChange: setTabOpen,
|
|
13772
|
+
onSelect: setTab,
|
|
13773
|
+
dataAttribute: "data-diff-tab-width-select"
|
|
13774
|
+
})
|
|
13775
|
+
]
|
|
13255
13776
|
});
|
|
13256
13777
|
}
|
|
13257
13778
|
//#endregion
|
|
@@ -13356,7 +13877,11 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13356
13877
|
const file = pendingFileOf(row);
|
|
13357
13878
|
if (file !== void 0) files.push(file);
|
|
13358
13879
|
}
|
|
13359
|
-
return {
|
|
13880
|
+
return value.redoCleared === true ? {
|
|
13881
|
+
files,
|
|
13882
|
+
workspacePath,
|
|
13883
|
+
redoCleared: true
|
|
13884
|
+
} : {
|
|
13360
13885
|
files,
|
|
13361
13886
|
workspacePath
|
|
13362
13887
|
};
|
|
@@ -13423,8 +13948,12 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13423
13948
|
busy: EMPTY_BUSY
|
|
13424
13949
|
};
|
|
13425
13950
|
const listeners = /* @__PURE__ */ new Set();
|
|
13951
|
+
let redoCleared = false;
|
|
13426
13952
|
const publish = (next) => {
|
|
13427
|
-
snapshot =
|
|
13953
|
+
snapshot = redoCleared ? {
|
|
13954
|
+
...next,
|
|
13955
|
+
redoCleared: true
|
|
13956
|
+
} : next;
|
|
13428
13957
|
for (const listener of [...listeners]) listener();
|
|
13429
13958
|
};
|
|
13430
13959
|
const failedOf = (value) => value.failed ?? EMPTY_FAILED;
|
|
@@ -13497,7 +14026,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13497
14026
|
return;
|
|
13498
14027
|
}
|
|
13499
14028
|
try {
|
|
13500
|
-
const { files, workspacePath } = await port.list(sessionId);
|
|
14029
|
+
const { files, workspacePath, redoCleared: cleared } = await port.list(sessionId);
|
|
14030
|
+
if (cleared) redoCleared = true;
|
|
13501
14031
|
publish({
|
|
13502
14032
|
read: true,
|
|
13503
14033
|
files,
|
|
@@ -13605,6 +14135,11 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13605
14135
|
files: [],
|
|
13606
14136
|
busy: EMPTY_BUSY
|
|
13607
14137
|
});
|
|
14138
|
+
},
|
|
14139
|
+
clearRedoCleared() {
|
|
14140
|
+
redoCleared = false;
|
|
14141
|
+
const { redoCleared: _omit, ...rest } = snapshot;
|
|
14142
|
+
publish(rest);
|
|
13608
14143
|
}
|
|
13609
14144
|
};
|
|
13610
14145
|
}
|
|
@@ -13627,11 +14162,15 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13627
14162
|
"panel.searchPlaceholder": "搜索",
|
|
13628
14163
|
"panel.missing": "文件已不存在",
|
|
13629
14164
|
"panel.missingHint": "该文件已不存在,回退会恢复该文件。",
|
|
14165
|
+
"panel.externalChanged": "检测到文件在外部被修改,已更新对比并新建撤销点;重做历史已被重置。",
|
|
14166
|
+
"panel.dismiss": "知道了",
|
|
13630
14167
|
"panel.createHint": "回退会删除该新建的文件。",
|
|
13631
14168
|
"panel.pasteOnCopy": "复制引用后自动粘贴到消息输入框",
|
|
13632
14169
|
"panel.pasteOnCopyDesc": "开启后,复制的引用会自动填入消息输入框,输入框会获得焦点。",
|
|
13633
14170
|
"panel.importUntracked": "导入未跟踪的文件改动",
|
|
13634
14171
|
"panel.importUntrackedDesc": "开启后,导入工作区改动会包含未跟踪/未版本化的新增文件(Git 未跟踪、SVN 未版本化、Perforce 未版本化)。收集改动需要扫描整个工作区,文件数量大时可能较慢。",
|
|
14172
|
+
"panel.tabWidth": "Tab 宽度",
|
|
14173
|
+
"panel.tabWidthDesc": "diff 中制表符(Tab)的缩进宽度,可选 2 / 4 / 8 个空格(默认 4),同时作用于行宽折行测量。",
|
|
13635
14174
|
"settings.tabLabel": "改动审批",
|
|
13636
14175
|
"row.create": "新增文件",
|
|
13637
14176
|
"row.failed": "失败",
|
|
@@ -13646,11 +14185,14 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13646
14185
|
"action.busy": "处理中…",
|
|
13647
14186
|
"action.prevDiff": "上一处差异",
|
|
13648
14187
|
"action.nextDiff": "下一处差异",
|
|
14188
|
+
"action.showFileList": "展开文件列表",
|
|
14189
|
+
"action.hideFileList": "收起文件列表",
|
|
13649
14190
|
"action.copyHint": "复制引用",
|
|
13650
14191
|
"action.copied": "已复制",
|
|
13651
14192
|
"action.langAuto": "自动",
|
|
13652
14193
|
"action.langAutoDetected": "自动:{lang}",
|
|
13653
14194
|
"action.langSelect": "高亮语言",
|
|
14195
|
+
"action.wrap": "自动换行",
|
|
13654
14196
|
"action.toggleOn": "打开",
|
|
13655
14197
|
"action.toggleOff": "关闭",
|
|
13656
14198
|
"action.importVcs": "导入工作区改动",
|
|
@@ -13683,11 +14225,15 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13683
14225
|
"panel.searchPlaceholder": "Search",
|
|
13684
14226
|
"panel.missing": "File is gone",
|
|
13685
14227
|
"panel.missingHint": "This file no longer exists; reverting restores it.",
|
|
14228
|
+
"panel.externalChanged": "A file changed outside the review. The comparison was updated and a new undo point created; the redo history was reset.",
|
|
14229
|
+
"panel.dismiss": "Got it",
|
|
13686
14230
|
"panel.createHint": "Reverting removes this created file.",
|
|
13687
14231
|
"panel.pasteOnCopy": "Paste the copied reference into the composer",
|
|
13688
14232
|
"panel.pasteOnCopyDesc": "When enabled, a copied reference is pasted into the composer, which then receives focus.",
|
|
13689
14233
|
"panel.importUntracked": "Import changes to untracked files",
|
|
13690
14234
|
"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.",
|
|
14235
|
+
"panel.tabWidth": "Tab width",
|
|
14236
|
+
"panel.tabWidthDesc": "The indent width of a tab character in the diff, as 2 / 4 / 8 spaces (default 4). Also drives the wrapped-line measurement.",
|
|
13691
14237
|
"settings.tabLabel": "Diff Approval",
|
|
13692
14238
|
"row.create": "New file",
|
|
13693
14239
|
"row.failed": "Failed",
|
|
@@ -13702,11 +14248,14 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13702
14248
|
"action.busy": "Working…",
|
|
13703
14249
|
"action.prevDiff": "Previous diff",
|
|
13704
14250
|
"action.nextDiff": "Next diff",
|
|
14251
|
+
"action.showFileList": "Show file list",
|
|
14252
|
+
"action.hideFileList": "Hide file list",
|
|
13705
14253
|
"action.copyHint": "Copy reference",
|
|
13706
14254
|
"action.copied": "Copied",
|
|
13707
14255
|
"action.langAuto": "Auto",
|
|
13708
14256
|
"action.langAutoDetected": "Auto: {lang}",
|
|
13709
14257
|
"action.langSelect": "Highlight language",
|
|
14258
|
+
"action.wrap": "Wrap lines",
|
|
13710
14259
|
"action.toggleOn": "On",
|
|
13711
14260
|
"action.toggleOff": "Off",
|
|
13712
14261
|
"action.importVcs": "Import workspace changes",
|
|
@@ -13765,6 +14314,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13765
14314
|
onUndo: (sessionId) => store.undo(sessionId),
|
|
13766
14315
|
onRedo: (sessionId) => store.redo(sessionId),
|
|
13767
14316
|
onImportVcs: (sessionId, includeUntracked) => store.importVcs(sessionId, includeUntracked),
|
|
14317
|
+
onAckRedoCleared: () => store.clearRedoCleared(),
|
|
13768
14318
|
onPasteReference: (sessionId, reference) => {
|
|
13769
14319
|
const actx = ctx.get("sessions")?.scope(sessionId);
|
|
13770
14320
|
if (actx === void 0) return;
|