dsh-diff-approval 0.9.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 +685 -159
- package/lib/types/client/PendingPanel.d.ts +1 -0
- package/lib/types/client/SettingsTab.d.ts +5 -4
- package/lib/types/client/locales.d.ts +10 -0
- package/lib/types/client/settings.d.ts +19 -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}.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)}";
|
|
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,95 +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
|
-
"
|
|
11666
|
-
"
|
|
11695
|
+
"badge": "F1KBNa_badge",
|
|
11696
|
+
"panel": "F1KBNa_panel",
|
|
11697
|
+
"settingsRow": "F1KBNa_settingsRow",
|
|
11698
|
+
"searchBar": "F1KBNa_searchBar",
|
|
11699
|
+
"detail": "F1KBNa_detail",
|
|
11700
|
+
"diffActions": "F1KBNa_diffActions",
|
|
11701
|
+
"markerAdd": "F1KBNa_markerAdd",
|
|
11702
|
+
"diff": "F1KBNa_diff",
|
|
11703
|
+
"gutter": "F1KBNa_gutter",
|
|
11704
|
+
"missingHint": "F1KBNa_missingHint",
|
|
11705
|
+
"wrap": "F1KBNa_wrap",
|
|
11706
|
+
"diffHeader": "F1KBNa_diffHeader",
|
|
11707
|
+
"context": "F1KBNa_context",
|
|
11667
11708
|
"importNote": "F1KBNa_importNote",
|
|
11668
|
-
"detailEmpty": "F1KBNa_detailEmpty",
|
|
11669
11709
|
"divergedHint": "F1KBNa_divergedHint",
|
|
11670
|
-
"
|
|
11671
|
-
"
|
|
11710
|
+
"listScroll": "F1KBNa_listScroll",
|
|
11711
|
+
"statusBar": "F1KBNa_statusBar",
|
|
11712
|
+
"readError": "F1KBNa_readError",
|
|
11672
11713
|
"settingsRowDesc": "F1KBNa_settingsRowDesc",
|
|
11673
|
-
"
|
|
11714
|
+
"settingsRowText": "F1KBNa_settingsRowText",
|
|
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",
|
|
11674
11729
|
"searchCount": "F1KBNa_searchCount",
|
|
11675
|
-
"
|
|
11676
|
-
"settingsRowTitle": "F1KBNa_settingsRowTitle",
|
|
11677
|
-
"title": "F1KBNa_title",
|
|
11678
|
-
"hint": "F1KBNa_hint",
|
|
11679
|
-
"overviewRuler": "F1KBNa_overviewRuler",
|
|
11680
|
-
"gutter": "F1KBNa_gutter",
|
|
11681
|
-
"code": "F1KBNa_code",
|
|
11682
|
-
"badge": "F1KBNa_badge",
|
|
11683
|
-
"badgeLabel": "F1KBNa_badgeLabel",
|
|
11730
|
+
"wrapActive": "F1KBNa_wrapActive",
|
|
11684
11731
|
"rail": "F1KBNa_rail",
|
|
11732
|
+
"overviewRuler": "F1KBNa_overviewRuler",
|
|
11685
11733
|
"diffBody": "F1KBNa_diffBody",
|
|
11734
|
+
"vSpacer": "F1KBNa_vSpacer",
|
|
11735
|
+
"title": "F1KBNa_title",
|
|
11686
11736
|
"rowMeta": "F1KBNa_rowMeta",
|
|
11687
|
-
"resizeHandle": "F1KBNa_resizeHandle",
|
|
11688
|
-
"kindTag": "F1KBNa_kindTag",
|
|
11689
|
-
"states": "F1KBNa_states",
|
|
11690
|
-
"panel": "F1KBNa_panel",
|
|
11691
|
-
"diff": "F1KBNa_diff",
|
|
11692
|
-
"statusAction": "F1KBNa_statusAction",
|
|
11693
|
-
"blockPosition": "F1KBNa_blockPosition",
|
|
11694
|
-
"notice": "F1KBNa_notice",
|
|
11695
|
-
"noticeText": "F1KBNa_noticeText",
|
|
11696
|
-
"rowFailed": "F1KBNa_rowFailed",
|
|
11697
|
-
"context": "F1KBNa_context",
|
|
11698
|
-
"del": "F1KBNa_del",
|
|
11699
|
-
"markerDel": "F1KBNa_markerDel",
|
|
11700
|
-
"langLabel": "F1KBNa_langLabel",
|
|
11701
|
-
"missing": "F1KBNa_missing",
|
|
11702
11737
|
"diffStats": "F1KBNa_diffStats",
|
|
11703
|
-
"
|
|
11738
|
+
"blockPosition": "F1KBNa_blockPosition",
|
|
11739
|
+
"searchInput": "F1KBNa_searchInput",
|
|
11740
|
+
"bulkActions": "F1KBNa_bulkActions",
|
|
11741
|
+
"noteCentered": "F1KBNa_noteCentered",
|
|
11704
11742
|
"blockFlash": "F1KBNa_blockFlash",
|
|
11705
|
-
"
|
|
11706
|
-
"
|
|
11743
|
+
"actionQuietDisabled": "F1KBNa_actionQuietDisabled",
|
|
11744
|
+
"code": "F1KBNa_code",
|
|
11745
|
+
"langSelect": "F1KBNa_langSelect",
|
|
11746
|
+
"kindTag": "F1KBNa_kindTag",
|
|
11707
11747
|
"diffFlash": "F1KBNa_diffFlash",
|
|
11708
|
-
"
|
|
11709
|
-
"
|
|
11710
|
-
"statusBar": "F1KBNa_statusBar",
|
|
11711
|
-
"listScroll": "F1KBNa_listScroll",
|
|
11712
|
-
"expandExpanded": "F1KBNa_expandExpanded",
|
|
11713
|
-
"lines": "F1KBNa_lines",
|
|
11714
|
-
"readError": "F1KBNa_readError",
|
|
11748
|
+
"footerButtons": "F1KBNa_footerButtons",
|
|
11749
|
+
"missing": "F1KBNa_missing",
|
|
11715
11750
|
"layer": "F1KBNa_layer",
|
|
11716
|
-
"
|
|
11717
|
-
"
|
|
11718
|
-
"
|
|
11719
|
-
"fullscreenBackdrop": "F1KBNa_fullscreenBackdrop",
|
|
11720
|
-
"diffBodyWrap": "F1KBNa_diffBodyWrap",
|
|
11721
|
-
"diffHeader": "F1KBNa_diffHeader",
|
|
11722
|
-
"rowPath": "F1KBNa_rowPath",
|
|
11723
|
-
"headerActions": "F1KBNa_headerActions",
|
|
11724
|
-
"kindHint": "F1KBNa_kindHint",
|
|
11725
|
-
"diffPath": "F1KBNa_diffPath",
|
|
11751
|
+
"noticeButton": "F1KBNa_noticeButton",
|
|
11752
|
+
"fileList": "F1KBNa_fileList",
|
|
11753
|
+
"add": "F1KBNa_add",
|
|
11726
11754
|
"split": "F1KBNa_split",
|
|
11727
|
-
"importButton": "F1KBNa_importButton",
|
|
11728
|
-
"diffActions": "F1KBNa_diffActions",
|
|
11729
|
-
"delCount": "F1KBNa_delCount",
|
|
11730
|
-
"rowHead": "F1KBNa_rowHead",
|
|
11731
11755
|
"overviewMarker": "F1KBNa_overviewMarker",
|
|
11732
|
-
"
|
|
11733
|
-
"searchInput": "F1KBNa_searchInput",
|
|
11734
|
-
"markerAdd": "F1KBNa_markerAdd",
|
|
11735
|
-
"vSpacer": "F1KBNa_vSpacer",
|
|
11736
|
-
"settingsRowText": "F1KBNa_settingsRowText",
|
|
11737
|
-
"missingHint": "F1KBNa_missingHint",
|
|
11738
|
-
"group": "F1KBNa_group",
|
|
11739
|
-
"emptyState": "F1KBNa_emptyState",
|
|
11740
|
-
"bulkActions": "F1KBNa_bulkActions",
|
|
11756
|
+
"resizeHandle": "F1KBNa_resizeHandle",
|
|
11741
11757
|
"settingsSelector": "F1KBNa_settingsSelector",
|
|
11742
|
-
"
|
|
11758
|
+
"badgeLabel": "F1KBNa_badgeLabel",
|
|
11759
|
+
"fileListFloat": "F1KBNa_fileListFloat",
|
|
11760
|
+
"expand": "F1KBNa_expand",
|
|
11761
|
+
"diffBodyWrap": "F1KBNa_diffBodyWrap",
|
|
11762
|
+
"lines": "F1KBNa_lines",
|
|
11763
|
+
"action": "F1KBNa_action",
|
|
11764
|
+
"statusAction": "F1KBNa_statusAction",
|
|
11765
|
+
"notice": "F1KBNa_notice",
|
|
11766
|
+
"fullscreenBackdrop": "F1KBNa_fullscreenBackdrop",
|
|
11743
11767
|
"settingsSelectorChevron": "F1KBNa_settingsSelectorChevron",
|
|
11744
|
-
"
|
|
11745
|
-
"
|
|
11746
|
-
"
|
|
11747
|
-
"
|
|
11748
|
-
"
|
|
11768
|
+
"delCount": "F1KBNa_delCount",
|
|
11769
|
+
"flexSpacer": "F1KBNa_flexSpacer",
|
|
11770
|
+
"markerDel": "F1KBNa_markerDel",
|
|
11771
|
+
"note": "F1KBNa_note",
|
|
11772
|
+
"states": "F1KBNa_states",
|
|
11773
|
+
"rowFailed": "F1KBNa_rowFailed",
|
|
11749
11774
|
"settingsPage": "F1KBNa_settingsPage",
|
|
11750
|
-
"
|
|
11751
|
-
"
|
|
11752
|
-
"
|
|
11753
|
-
"
|
|
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"
|
|
11754
11788
|
};
|
|
11755
11789
|
//#endregion
|
|
11756
11790
|
//#region lib/types/client/PendingPanel.js
|
|
@@ -11782,8 +11816,144 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11782
11816
|
/** File-list pane width bounds for the manual split drag, in px. */
|
|
11783
11817
|
const MIN_LIST_WIDTH_PX = 160;
|
|
11784
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;
|
|
11785
11821
|
/** Fixed diff-row height in px; the virtual window and jump math are built on it. */
|
|
11786
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
|
+
}
|
|
11787
11957
|
/** The overview ruler's width in px (mirrors `.overviewRuler`). The flash is
|
|
11788
11958
|
* kept off it even when the scroller has no vertical scrollbar. */
|
|
11789
11959
|
const OVERVIEW_RULER_WIDTH_PX = 4;
|
|
@@ -11799,6 +11969,22 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11799
11969
|
return index < 0 ? path : path.slice(index + 1);
|
|
11800
11970
|
}
|
|
11801
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
|
+
/**
|
|
11802
11988
|
* Open the DSH settings dialog and switch to this plugin's section. The
|
|
11803
11989
|
* settings shell keeps its open state and the active section id as
|
|
11804
11990
|
* component-local viewing state with no cross-plugin service, so the dialog
|
|
@@ -11824,18 +12010,56 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11824
12010
|
/** Empty failure map reused as the snapshot's canonical absent value. */
|
|
11825
12011
|
const EMPTY_FAILED_MAP = /* @__PURE__ */ new Map();
|
|
11826
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
|
+
/**
|
|
11827
12034
|
* One rendered diff row, memoized so a poll or an unrelated state change
|
|
11828
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.
|
|
11829
12039
|
*/
|
|
11830
12040
|
const DiffRow = (0, react.memo)(function DiffRow(props) {
|
|
11831
|
-
const { index, row, runs, focused, searchHit, searchCurrent, onRowHover } = props;
|
|
12041
|
+
const { index, row, runs, focused, searchHit, searchCurrent, onRowHover, wrappedLines } = props;
|
|
11832
12042
|
const lineNumber = row.kind === "del" ? row.oldLine : row.newLine;
|
|
11833
12043
|
const sideRuns = row.kind === "del" ? runs?.oldRuns : runs?.newRuns;
|
|
11834
12044
|
const lineRuns = lineNumber === void 0 ? void 0 : sideRuns?.[lineNumber - 1];
|
|
11835
|
-
|
|
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", {
|
|
11836
12047
|
style: span.style,
|
|
11837
12048
|
children: span.text
|
|
11838
|
-
}, 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
|
+
}
|
|
11839
12063
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
11840
12064
|
className: `${PendingPanel_module_css_default.line} ${ROW_CLASS[row.kind]}`,
|
|
11841
12065
|
"data-diff-line": row.kind,
|
|
@@ -11857,7 +12081,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11857
12081
|
(0, react_jsx_runtime.jsx)("span", {
|
|
11858
12082
|
className: PendingPanel_module_css_default.code,
|
|
11859
12083
|
"data-diff-code": true,
|
|
11860
|
-
children:
|
|
12084
|
+
children: code
|
|
11861
12085
|
})
|
|
11862
12086
|
]
|
|
11863
12087
|
});
|
|
@@ -12034,7 +12258,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12034
12258
|
});
|
|
12035
12259
|
}
|
|
12036
12260
|
/** The selected file's diff, actions, jump controls, and copy toolbar. */
|
|
12037
|
-
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 }) {
|
|
12038
12262
|
const [langOverride, setLangOverride] = (0, react.useState)(void 0);
|
|
12039
12263
|
const [langMenuOpen, setLangMenuOpen] = (0, react.useState)(false);
|
|
12040
12264
|
const langMenuItems = (0, react.useMemo)(() => [{
|
|
@@ -12047,6 +12271,17 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12047
12271
|
const detectedLang = (0, react.useMemo)(() => langFromPath(file.path), [file.path]);
|
|
12048
12272
|
const lang = (0, react.useMemo)(() => langOverride ?? detectedLang, [detectedLang, langOverride]);
|
|
12049
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());
|
|
12050
12285
|
const model = (0, react.useMemo)(() => {
|
|
12051
12286
|
const diff = computeWholeFileDiff(file.oldText, file.newText);
|
|
12052
12287
|
return {
|
|
@@ -12112,6 +12347,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12112
12347
|
const [scrollTick, setScrollTick] = (0, react.useState)(0);
|
|
12113
12348
|
const [scrollTop, setScrollTop] = (0, react.useState)(0);
|
|
12114
12349
|
const [viewportHeight, setViewportHeight] = (0, react.useState)(0);
|
|
12350
|
+
const [bodyWidth, setBodyWidth] = (0, react.useState)(0);
|
|
12351
|
+
const [hScrollbarPx, setHScrollbarPx] = (0, react.useState)(0);
|
|
12115
12352
|
const [hoveredBlock, setHoveredBlock] = (0, react.useState)(void 0);
|
|
12116
12353
|
const [selection, setSelection] = (0, react.useState)(void 0);
|
|
12117
12354
|
const [copied, setCopied] = (0, react.useState)(false);
|
|
@@ -12178,7 +12415,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12178
12415
|
if (row === void 0) return;
|
|
12179
12416
|
const body = bodyRef.current;
|
|
12180
12417
|
if (body === null) return;
|
|
12181
|
-
const target = row
|
|
12418
|
+
const target = offsetOf(row) + extentOf(row, row) / 2 - body.clientHeight / 2;
|
|
12182
12419
|
const clamped = Math.max(0, Math.min(target, body.scrollHeight - body.clientHeight));
|
|
12183
12420
|
if (body.scrollTop !== clamped) body.scrollTop = clamped;
|
|
12184
12421
|
setScrollTop(clamped);
|
|
@@ -12195,12 +12432,58 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12195
12432
|
}, [blockIndexByRow]);
|
|
12196
12433
|
const rows = model.diff.rows;
|
|
12197
12434
|
const rowCount = rows.length;
|
|
12198
|
-
const
|
|
12199
|
-
|
|
12200
|
-
|
|
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);
|
|
12201
12484
|
const visibleRows = rows.slice(start, end);
|
|
12202
|
-
const
|
|
12203
|
-
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));
|
|
12204
12487
|
const widestLine = (0, react.useMemo)(() => {
|
|
12205
12488
|
let widest = 0;
|
|
12206
12489
|
for (const row of model.diff.rows) if (row.text.length > widest) widest = row.text.length;
|
|
@@ -12219,13 +12502,27 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12219
12502
|
observer?.disconnect();
|
|
12220
12503
|
};
|
|
12221
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]);
|
|
12222
12519
|
(0, react.useLayoutEffect)(() => {
|
|
12223
12520
|
if (rowCount === 0) return;
|
|
12224
12521
|
const block = model.blocks[focus];
|
|
12225
12522
|
if (block === void 0) return;
|
|
12226
12523
|
const body = bodyRef.current;
|
|
12227
12524
|
if (body === null) return;
|
|
12228
|
-
const target = block.start
|
|
12525
|
+
const target = offsetOf(block.start) - 44;
|
|
12229
12526
|
const clamped = Math.max(0, Math.min(target, body.scrollHeight - body.clientHeight));
|
|
12230
12527
|
if (body.scrollTop !== clamped) body.scrollTop = clamped;
|
|
12231
12528
|
setScrollTop(clamped);
|
|
@@ -12233,7 +12530,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12233
12530
|
model,
|
|
12234
12531
|
focus,
|
|
12235
12532
|
scrollTick,
|
|
12236
|
-
rowCount
|
|
12533
|
+
rowCount,
|
|
12534
|
+
rowOffsets === null
|
|
12237
12535
|
]);
|
|
12238
12536
|
const jump = (direction) => {
|
|
12239
12537
|
if (rowCount === 0) return;
|
|
@@ -12243,13 +12541,22 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12243
12541
|
for (let index = current + 1; index < model.blocks.length; index++) {
|
|
12244
12542
|
const block = model.blocks[index];
|
|
12245
12543
|
if (block === void 0) continue;
|
|
12246
|
-
if (block.start
|
|
12544
|
+
if (offsetOf(block.start) >= top) return index;
|
|
12247
12545
|
}
|
|
12248
12546
|
return 0;
|
|
12249
12547
|
});
|
|
12250
12548
|
setScrollTick((tick) => tick + 1);
|
|
12251
12549
|
setFlashKey((key) => key + 1);
|
|
12252
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
|
+
};
|
|
12253
12560
|
(0, react.useEffect)(() => {
|
|
12254
12561
|
if (jumpSignal === 0) return;
|
|
12255
12562
|
jump(1);
|
|
@@ -12339,6 +12646,9 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12339
12646
|
const scrollbarWidth = scroller.offsetWidth - scroller.clientWidth;
|
|
12340
12647
|
return Math.max(0, scroller.clientWidth - (scrollbarWidth > 0 ? 0 : OVERVIEW_RULER_WIDTH_PX));
|
|
12341
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);
|
|
12342
12652
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
12343
12653
|
className: PendingPanel_module_css_default.diff,
|
|
12344
12654
|
"data-diff-approval-diff": true,
|
|
@@ -12385,6 +12695,19 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12385
12695
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
12386
12696
|
className: PendingPanel_module_css_default.diffActions,
|
|
12387
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
|
+
}),
|
|
12388
12711
|
(0, react_jsx_runtime.jsx)("span", {
|
|
12389
12712
|
className: PendingPanel_module_css_default.diffStats,
|
|
12390
12713
|
children: t("panel.stats", {
|
|
@@ -12483,14 +12806,18 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12483
12806
|
onMouseLeave: () => {
|
|
12484
12807
|
setHoveredBlock(void 0);
|
|
12485
12808
|
},
|
|
12809
|
+
style: { tabSize: tabWidthSpaces },
|
|
12486
12810
|
"data-diff-body": true,
|
|
12487
12811
|
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
12488
|
-
className: PendingPanel_module_css_default.lines
|
|
12489
|
-
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)` },
|
|
12490
12817
|
children: [
|
|
12491
12818
|
start > 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
12492
12819
|
className: PendingPanel_module_css_default.vSpacer,
|
|
12493
|
-
style: { height: start
|
|
12820
|
+
style: { height: offsetOf(start) },
|
|
12494
12821
|
"aria-hidden": "true"
|
|
12495
12822
|
}),
|
|
12496
12823
|
visibleRows.map((row, offset) => {
|
|
@@ -12502,24 +12829,20 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12502
12829
|
focused: inFocusedBlock(index),
|
|
12503
12830
|
searchHit: searchHitSet.has(index),
|
|
12504
12831
|
searchCurrent: index === currentSearchRow,
|
|
12505
|
-
onRowHover
|
|
12832
|
+
onRowHover,
|
|
12833
|
+
wrappedLines: rowWrapped?.[index]
|
|
12506
12834
|
}, index);
|
|
12507
12835
|
}),
|
|
12508
12836
|
end < rowCount && (0, react_jsx_runtime.jsx)("div", {
|
|
12509
12837
|
className: PendingPanel_module_css_default.vSpacer,
|
|
12510
|
-
style: { height:
|
|
12511
|
-
"aria-hidden": "true"
|
|
12512
|
-
}),
|
|
12513
|
-
blockActionsPadPx > 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
12514
|
-
className: PendingPanel_module_css_default.vSpacer,
|
|
12515
|
-
style: { height: blockActionsPadPx },
|
|
12838
|
+
style: { height: totalHeight - offsetOf(end) },
|
|
12516
12839
|
"aria-hidden": "true"
|
|
12517
12840
|
})
|
|
12518
12841
|
]
|
|
12519
12842
|
}), hoveredBlock !== void 0 && model.blocks[hoveredBlock] !== void 0 && (0, react_jsx_runtime.jsxs)("div", {
|
|
12520
12843
|
className: PendingPanel_module_css_default.blockActions,
|
|
12521
12844
|
"data-diff-block-actions": true,
|
|
12522
|
-
style: { top:
|
|
12845
|
+
style: { top: blockActionsTop },
|
|
12523
12846
|
children: [
|
|
12524
12847
|
(0, react_jsx_runtime.jsx)("span", {
|
|
12525
12848
|
className: PendingPanel_module_css_default.blockPosition,
|
|
@@ -12529,6 +12852,28 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12529
12852
|
total: model.blocks.length
|
|
12530
12853
|
})
|
|
12531
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
|
+
}),
|
|
12532
12877
|
(0, react_jsx_runtime.jsx)("button", {
|
|
12533
12878
|
type: "button",
|
|
12534
12879
|
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.actionPrimary}`,
|
|
@@ -12556,8 +12901,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12556
12901
|
className: PendingPanel_module_css_default.blockFlash,
|
|
12557
12902
|
"data-diff-block-flash": true,
|
|
12558
12903
|
style: {
|
|
12559
|
-
top:
|
|
12560
|
-
height:
|
|
12904
|
+
top: flashTop,
|
|
12905
|
+
height: flashHeight,
|
|
12561
12906
|
width: flashWidth
|
|
12562
12907
|
}
|
|
12563
12908
|
}, flashKey),
|
|
@@ -12622,6 +12967,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12622
12967
|
className: PendingPanel_module_css_default.overviewRuler,
|
|
12623
12968
|
"data-diff-approval-ruler": true,
|
|
12624
12969
|
"aria-hidden": "true",
|
|
12970
|
+
style: { bottom: hScrollbarPx },
|
|
12625
12971
|
children: rulerMarkers.map((marker, index) => (0, react_jsx_runtime.jsx)("div", {
|
|
12626
12972
|
className: `${PendingPanel_module_css_default.overviewMarker} ${marker.kind === "del" ? PendingPanel_module_css_default.markerDel : PendingPanel_module_css_default.markerAdd}`,
|
|
12627
12973
|
"data-diff-ruler-marker": marker.kind,
|
|
@@ -12687,6 +13033,23 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12687
13033
|
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 12 })]
|
|
12688
13034
|
})
|
|
12689
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
|
+
})
|
|
12690
13053
|
})
|
|
12691
13054
|
]
|
|
12692
13055
|
})
|
|
@@ -12731,6 +13094,16 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12731
13094
|
/** File-list pane width, adjustable by dragging the divider. */
|
|
12732
13095
|
const [listWidth, setListWidth] = (0, react.useState)(240);
|
|
12733
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);
|
|
12734
13107
|
(0, react.useEffect)(() => {
|
|
12735
13108
|
onRefresh(current);
|
|
12736
13109
|
const timer = setInterval(() => {
|
|
@@ -12740,6 +13113,55 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12740
13113
|
clearInterval(timer);
|
|
12741
13114
|
};
|
|
12742
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
|
+
]);
|
|
12743
13165
|
(0, react.useEffect)(() => {
|
|
12744
13166
|
if (!open || !snapshot.redoCleared) return;
|
|
12745
13167
|
onAckRedoCleared();
|
|
@@ -12792,7 +13214,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12792
13214
|
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
12793
13215
|
};
|
|
12794
13216
|
}, [open]);
|
|
12795
|
-
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));
|
|
12796
13218
|
/** Per-file keep/revert failures, surfaced inline on the row and detail. */
|
|
12797
13219
|
const failed = snapshot.failed ?? EMPTY_FAILED_MAP;
|
|
12798
13220
|
const failedInitialized = (0, react.useRef)(false);
|
|
@@ -12865,6 +13287,37 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12865
13287
|
}
|
|
12866
13288
|
}, entry.id);
|
|
12867
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
|
+
})] });
|
|
12868
13321
|
const handleUndo = async (sessionId) => {
|
|
12869
13322
|
const id = await onUndo(sessionId);
|
|
12870
13323
|
if (id === void 0) return;
|
|
@@ -12948,6 +13401,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12948
13401
|
}),
|
|
12949
13402
|
open && (0, react_jsx_runtime.jsxs)("section", {
|
|
12950
13403
|
className: PendingPanel_module_css_default.panel,
|
|
13404
|
+
ref: panelRef,
|
|
12951
13405
|
style: { bottom: expanded ? PANEL_INSET_PX : bottomPx },
|
|
12952
13406
|
"data-diff-approval-panel": true,
|
|
12953
13407
|
"aria-label": t("panel.title"),
|
|
@@ -13046,44 +13500,15 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13046
13500
|
]
|
|
13047
13501
|
}) : (0, react_jsx_runtime.jsxs)("div", {
|
|
13048
13502
|
className: PendingPanel_module_css_default.split,
|
|
13503
|
+
ref: splitRef,
|
|
13049
13504
|
children: [
|
|
13050
|
-
(0, react_jsx_runtime.
|
|
13505
|
+
!floatMode && (0, react_jsx_runtime.jsx)("nav", {
|
|
13051
13506
|
className: PendingPanel_module_css_default.fileList,
|
|
13052
13507
|
style: { width: listWidth },
|
|
13053
13508
|
"data-diff-approval-file-list": true,
|
|
13054
|
-
children:
|
|
13055
|
-
className: PendingPanel_module_css_default.listScroll,
|
|
13056
|
-
children: files.length > 0 && (0, react_jsx_runtime.jsxs)("section", { children: [(0, react_jsx_runtime.jsx)("h3", {
|
|
13057
|
-
className: PendingPanel_module_css_default.group,
|
|
13058
|
-
children: t("panel.group.current")
|
|
13059
|
-
}), (0, react_jsx_runtime.jsx)("ul", {
|
|
13060
|
-
className: PendingPanel_module_css_default.rows,
|
|
13061
|
-
children: files.map(renderEntry)
|
|
13062
|
-
})] })
|
|
13063
|
-
}), files.length > 0 && (0, react_jsx_runtime.jsxs)("div", {
|
|
13064
|
-
className: PendingPanel_module_css_default.bulkActions,
|
|
13065
|
-
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
13066
|
-
type: "button",
|
|
13067
|
-
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.actionPrimary}`,
|
|
13068
|
-
"data-diff-keep-all": true,
|
|
13069
|
-
disabled: bulkBusy !== null,
|
|
13070
|
-
onClick: () => {
|
|
13071
|
-
runBulk("keep");
|
|
13072
|
-
},
|
|
13073
|
-
children: bulkBusy === "keep" ? t("action.busy") : t("action.keepAll")
|
|
13074
|
-
}), (0, react_jsx_runtime.jsx)("button", {
|
|
13075
|
-
type: "button",
|
|
13076
|
-
className: PendingPanel_module_css_default.action,
|
|
13077
|
-
"data-diff-revert-all": true,
|
|
13078
|
-
disabled: bulkBusy !== null,
|
|
13079
|
-
onClick: () => {
|
|
13080
|
-
runBulk("revert");
|
|
13081
|
-
},
|
|
13082
|
-
children: bulkBusy === "revert" ? t("action.busy") : t("action.revertAll")
|
|
13083
|
-
})]
|
|
13084
|
-
})]
|
|
13509
|
+
children: fileListBody
|
|
13085
13510
|
}),
|
|
13086
|
-
(0, react_jsx_runtime.jsx)("div", {
|
|
13511
|
+
!floatMode && (0, react_jsx_runtime.jsx)("div", {
|
|
13087
13512
|
className: PendingPanel_module_css_default.resizeHandle,
|
|
13088
13513
|
"data-diff-resize": true,
|
|
13089
13514
|
onMouseDown: startResize
|
|
@@ -13106,8 +13531,22 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13106
13531
|
onRevert,
|
|
13107
13532
|
onBlockKeep,
|
|
13108
13533
|
onBlockRevert,
|
|
13109
|
-
onOpen
|
|
13534
|
+
onOpen,
|
|
13535
|
+
floatMode,
|
|
13536
|
+
floatOpen,
|
|
13537
|
+
onToggleFileList: toggleFileList
|
|
13110
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
|
|
13111
13550
|
})
|
|
13112
13551
|
]
|
|
13113
13552
|
})]
|
|
@@ -13216,17 +13655,78 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13216
13655
|
})]
|
|
13217
13656
|
});
|
|
13218
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
|
+
}
|
|
13219
13716
|
/**
|
|
13220
|
-
* The plugin's preferences: auto-paste a copied reference into the input,
|
|
13221
|
-
* whether importing workspace VCS changes includes untracked files
|
|
13222
|
-
* mirrors the harness's Agent-preset row (title +
|
|
13223
|
-
* 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.
|
|
13224
13722
|
*/
|
|
13225
13723
|
function DiffApprovalSettingsTab({ t }) {
|
|
13226
13724
|
const [pasteOnCopy, setPasteOnCopyState] = (0, react.useState)(pasteOnCopyEnabled);
|
|
13227
13725
|
const [pasteOnCopyOpen, setPasteOnCopyOpen] = (0, react.useState)(false);
|
|
13228
13726
|
const [includeUntracked, setIncludeUntrackedState] = (0, react.useState)(includeUntrackedEnabled);
|
|
13229
13727
|
const [includeUntrackedOpen, setIncludeUntrackedOpen] = (0, react.useState)(false);
|
|
13728
|
+
const [tab, setTabState] = (0, react.useState)(tabWidth);
|
|
13729
|
+
const [tabOpen, setTabOpen] = (0, react.useState)(false);
|
|
13230
13730
|
const setPasteOnCopy = (value) => {
|
|
13231
13731
|
setPasteOnCopyState(value);
|
|
13232
13732
|
setPasteOnCopyEnabled(value);
|
|
@@ -13235,28 +13735,44 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13235
13735
|
setIncludeUntrackedState(value);
|
|
13236
13736
|
setIncludeUntrackedEnabled(value);
|
|
13237
13737
|
};
|
|
13738
|
+
const setTab = (value) => {
|
|
13739
|
+
setTabState(value);
|
|
13740
|
+
setTabWidth(value);
|
|
13741
|
+
};
|
|
13238
13742
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
13239
13743
|
className: PendingPanel_module_css_default.settingsPage,
|
|
13240
13744
|
"data-diff-settings": true,
|
|
13241
|
-
children: [
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
13246
|
-
|
|
13247
|
-
|
|
13248
|
-
|
|
13249
|
-
|
|
13250
|
-
|
|
13251
|
-
|
|
13252
|
-
|
|
13253
|
-
|
|
13254
|
-
|
|
13255
|
-
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
|
|
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
|
+
]
|
|
13260
13776
|
});
|
|
13261
13777
|
}
|
|
13262
13778
|
//#endregion
|
|
@@ -13653,6 +14169,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13653
14169
|
"panel.pasteOnCopyDesc": "开启后,复制的引用会自动填入消息输入框,输入框会获得焦点。",
|
|
13654
14170
|
"panel.importUntracked": "导入未跟踪的文件改动",
|
|
13655
14171
|
"panel.importUntrackedDesc": "开启后,导入工作区改动会包含未跟踪/未版本化的新增文件(Git 未跟踪、SVN 未版本化、Perforce 未版本化)。收集改动需要扫描整个工作区,文件数量大时可能较慢。",
|
|
14172
|
+
"panel.tabWidth": "Tab 宽度",
|
|
14173
|
+
"panel.tabWidthDesc": "diff 中制表符(Tab)的缩进宽度,可选 2 / 4 / 8 个空格(默认 4),同时作用于行宽折行测量。",
|
|
13656
14174
|
"settings.tabLabel": "改动审批",
|
|
13657
14175
|
"row.create": "新增文件",
|
|
13658
14176
|
"row.failed": "失败",
|
|
@@ -13667,11 +14185,14 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13667
14185
|
"action.busy": "处理中…",
|
|
13668
14186
|
"action.prevDiff": "上一处差异",
|
|
13669
14187
|
"action.nextDiff": "下一处差异",
|
|
14188
|
+
"action.showFileList": "展开文件列表",
|
|
14189
|
+
"action.hideFileList": "收起文件列表",
|
|
13670
14190
|
"action.copyHint": "复制引用",
|
|
13671
14191
|
"action.copied": "已复制",
|
|
13672
14192
|
"action.langAuto": "自动",
|
|
13673
14193
|
"action.langAutoDetected": "自动:{lang}",
|
|
13674
14194
|
"action.langSelect": "高亮语言",
|
|
14195
|
+
"action.wrap": "自动换行",
|
|
13675
14196
|
"action.toggleOn": "打开",
|
|
13676
14197
|
"action.toggleOff": "关闭",
|
|
13677
14198
|
"action.importVcs": "导入工作区改动",
|
|
@@ -13711,6 +14232,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13711
14232
|
"panel.pasteOnCopyDesc": "When enabled, a copied reference is pasted into the composer, which then receives focus.",
|
|
13712
14233
|
"panel.importUntracked": "Import changes to untracked files",
|
|
13713
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.",
|
|
13714
14237
|
"settings.tabLabel": "Diff Approval",
|
|
13715
14238
|
"row.create": "New file",
|
|
13716
14239
|
"row.failed": "Failed",
|
|
@@ -13725,11 +14248,14 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13725
14248
|
"action.busy": "Working…",
|
|
13726
14249
|
"action.prevDiff": "Previous diff",
|
|
13727
14250
|
"action.nextDiff": "Next diff",
|
|
14251
|
+
"action.showFileList": "Show file list",
|
|
14252
|
+
"action.hideFileList": "Hide file list",
|
|
13728
14253
|
"action.copyHint": "Copy reference",
|
|
13729
14254
|
"action.copied": "Copied",
|
|
13730
14255
|
"action.langAuto": "Auto",
|
|
13731
14256
|
"action.langAutoDetected": "Auto: {lang}",
|
|
13732
14257
|
"action.langSelect": "Highlight language",
|
|
14258
|
+
"action.wrap": "Wrap lines",
|
|
13733
14259
|
"action.toggleOn": "On",
|
|
13734
14260
|
"action.toggleOff": "Off",
|
|
13735
14261
|
"action.importVcs": "Import workspace changes",
|