dsh-diff-approval 0.14.0 → 0.14.1
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/lib/client.js +107 -98
- package/lib/index.js +46 -13
- package/lib/types/client/PendingPanel.d.ts +9 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -11946,115 +11946,115 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11946
11946
|
document.head.appendChild(tag);
|
|
11947
11947
|
}
|
|
11948
11948
|
var PendingPanel_module_css_default = {
|
|
11949
|
-
"
|
|
11950
|
-
"
|
|
11951
|
-
"
|
|
11952
|
-
"subline": "F1KBNa_subline",
|
|
11953
|
-
"noteCentered": "F1KBNa_noteCentered",
|
|
11954
|
-
"splitDivider": "F1KBNa_splitDivider",
|
|
11955
|
-
"splitHScrollFill": "F1KBNa_splitHScrollFill",
|
|
11956
|
-
"action": "F1KBNa_action",
|
|
11957
|
-
"noticeText": "F1KBNa_noticeText",
|
|
11958
|
-
"header": "F1KBNa_header",
|
|
11959
|
-
"settingsRowTitle": "F1KBNa_settingsRowTitle",
|
|
11960
|
-
"confirmCard": "F1KBNa_confirmCard",
|
|
11961
|
-
"markerDel": "F1KBNa_markerDel",
|
|
11962
|
-
"wrapActive": "F1KBNa_wrapActive",
|
|
11963
|
-
"listScroll": "F1KBNa_listScroll",
|
|
11964
|
-
"hint": "F1KBNa_hint",
|
|
11965
|
-
"diffPath": "F1KBNa_diffPath",
|
|
11966
|
-
"splitLadd": "F1KBNa_splitLadd",
|
|
11967
|
-
"blockActions": "F1KBNa_blockActions",
|
|
11949
|
+
"confirmBackdrop": "F1KBNa_confirmBackdrop",
|
|
11950
|
+
"kindHint": "F1KBNa_kindHint",
|
|
11951
|
+
"splitRdel": "F1KBNa_splitRdel",
|
|
11968
11952
|
"missingHint": "F1KBNa_missingHint",
|
|
11969
|
-
"
|
|
11970
|
-
"
|
|
11953
|
+
"expandExpanded": "F1KBNa_expandExpanded",
|
|
11954
|
+
"readError": "F1KBNa_readError",
|
|
11955
|
+
"diffBody": "F1KBNa_diffBody",
|
|
11956
|
+
"lines": "F1KBNa_lines",
|
|
11971
11957
|
"langLabel": "F1KBNa_langLabel",
|
|
11972
|
-
"
|
|
11958
|
+
"splitCol": "F1KBNa_splitCol",
|
|
11973
11959
|
"splitRadd": "F1KBNa_splitRadd",
|
|
11974
|
-
"
|
|
11975
|
-
"
|
|
11960
|
+
"diffPath": "F1KBNa_diffPath",
|
|
11961
|
+
"diffActions": "F1KBNa_diffActions",
|
|
11962
|
+
"rowPath": "F1KBNa_rowPath",
|
|
11963
|
+
"listScroll": "F1KBNa_listScroll",
|
|
11964
|
+
"actionPrimary": "F1KBNa_actionPrimary",
|
|
11965
|
+
"importButton": "F1KBNa_importButton",
|
|
11966
|
+
"rows": "F1KBNa_rows",
|
|
11967
|
+
"searchCount": "F1KBNa_searchCount",
|
|
11968
|
+
"statusBar": "F1KBNa_statusBar",
|
|
11969
|
+
"footerButtons": "F1KBNa_footerButtons",
|
|
11970
|
+
"layer": "F1KBNa_layer",
|
|
11971
|
+
"badgeLabel": "F1KBNa_badgeLabel",
|
|
11976
11972
|
"divergedHint": "F1KBNa_divergedHint",
|
|
11977
|
-
"
|
|
11973
|
+
"actionError": "F1KBNa_actionError",
|
|
11974
|
+
"code": "F1KBNa_code",
|
|
11975
|
+
"splitDivider": "F1KBNa_splitDivider",
|
|
11976
|
+
"confirmCard": "F1KBNa_confirmCard",
|
|
11977
|
+
"title": "F1KBNa_title",
|
|
11978
|
+
"wrap": "F1KBNa_wrap",
|
|
11979
|
+
"statusAction": "F1KBNa_statusAction",
|
|
11980
|
+
"noticeButton": "F1KBNa_noticeButton",
|
|
11981
|
+
"flexSpacer": "F1KBNa_flexSpacer",
|
|
11982
|
+
"confirmActions": "F1KBNa_confirmActions",
|
|
11983
|
+
"searchInput": "F1KBNa_searchInput",
|
|
11984
|
+
"settingsRowText": "F1KBNa_settingsRowText",
|
|
11985
|
+
"header": "F1KBNa_header",
|
|
11986
|
+
"diffStats": "F1KBNa_diffStats",
|
|
11987
|
+
"settingsRowTitle": "F1KBNa_settingsRowTitle",
|
|
11988
|
+
"blockFlash": "F1KBNa_blockFlash",
|
|
11989
|
+
"row": "F1KBNa_row",
|
|
11990
|
+
"fullscreenBackdrop": "F1KBNa_fullscreenBackdrop",
|
|
11978
11991
|
"missing": "F1KBNa_missing",
|
|
11992
|
+
"actionQuietDisabled": "F1KBNa_actionQuietDisabled",
|
|
11993
|
+
"searchBar": "F1KBNa_searchBar",
|
|
11994
|
+
"overviewRuler": "F1KBNa_overviewRuler",
|
|
11995
|
+
"notice": "F1KBNa_notice",
|
|
11996
|
+
"splitCols": "F1KBNa_splitCols",
|
|
11979
11997
|
"markerAdd": "F1KBNa_markerAdd",
|
|
11998
|
+
"splitRoot": "F1KBNa_splitRoot",
|
|
11999
|
+
"blockPosition": "F1KBNa_blockPosition",
|
|
12000
|
+
"overviewMarker": "F1KBNa_overviewMarker",
|
|
12001
|
+
"noticeText": "F1KBNa_noticeText",
|
|
12002
|
+
"iconAction": "F1KBNa_iconAction",
|
|
12003
|
+
"splitHScrollRow": "F1KBNa_splitHScrollRow",
|
|
12004
|
+
"delCount": "F1KBNa_delCount",
|
|
12005
|
+
"splitLadd": "F1KBNa_splitLadd",
|
|
12006
|
+
"hint": "F1KBNa_hint",
|
|
12007
|
+
"splitHScroll": "F1KBNa_splitHScroll",
|
|
12008
|
+
"note": "F1KBNa_note",
|
|
12009
|
+
"settingsPage": "F1KBNa_settingsPage",
|
|
12010
|
+
"splitLdel": "F1KBNa_splitLdel",
|
|
12011
|
+
"rail": "F1KBNa_rail",
|
|
11980
12012
|
"del": "F1KBNa_del",
|
|
12013
|
+
"noteCentered": "F1KBNa_noteCentered",
|
|
12014
|
+
"line": "F1KBNa_line",
|
|
12015
|
+
"action": "F1KBNa_action",
|
|
12016
|
+
"fileList": "F1KBNa_fileList",
|
|
12017
|
+
"rowMeta": "F1KBNa_rowMeta",
|
|
12018
|
+
"diffFlash": "F1KBNa_diffFlash",
|
|
11981
12019
|
"add": "F1KBNa_add",
|
|
12020
|
+
"settingsSelector": "F1KBNa_settingsSelector",
|
|
11982
12021
|
"detailEmpty": "F1KBNa_detailEmpty",
|
|
11983
|
-
"
|
|
11984
|
-
"title": "F1KBNa_title",
|
|
11985
|
-
"blockPosition": "F1KBNa_blockPosition",
|
|
11986
|
-
"badgeLabel": "F1KBNa_badgeLabel",
|
|
11987
|
-
"headerActions": "F1KBNa_headerActions",
|
|
11988
|
-
"panel": "F1KBNa_panel",
|
|
11989
|
-
"group": "F1KBNa_group",
|
|
11990
|
-
"blockFlash": "F1KBNa_blockFlash",
|
|
11991
|
-
"settingsRow": "F1KBNa_settingsRow",
|
|
11992
|
-
"importNote": "F1KBNa_importNote",
|
|
11993
|
-
"diffFlash": "F1KBNa_diffFlash",
|
|
11994
|
-
"notice": "F1KBNa_notice",
|
|
11995
|
-
"rowPath": "F1KBNa_rowPath",
|
|
11996
|
-
"readError": "F1KBNa_readError",
|
|
11997
|
-
"settingsPage": "F1KBNa_settingsPage",
|
|
11998
|
-
"settingsRowText": "F1KBNa_settingsRowText",
|
|
12022
|
+
"langSelect": "F1KBNa_langSelect",
|
|
11999
12023
|
"fileListFloat": "F1KBNa_fileListFloat",
|
|
12000
|
-
"
|
|
12024
|
+
"emptyState": "F1KBNa_emptyState",
|
|
12001
12025
|
"kindTag": "F1KBNa_kindTag",
|
|
12002
12026
|
"rowFailed": "F1KBNa_rowFailed",
|
|
12003
|
-
"
|
|
12004
|
-
"
|
|
12005
|
-
"
|
|
12006
|
-
"
|
|
12007
|
-
"
|
|
12008
|
-
"
|
|
12009
|
-
"
|
|
12027
|
+
"addCount": "F1KBNa_addCount",
|
|
12028
|
+
"wrapActive": "F1KBNa_wrapActive",
|
|
12029
|
+
"close": "F1KBNa_close",
|
|
12030
|
+
"diffHeader": "F1KBNa_diffHeader",
|
|
12031
|
+
"badge": "F1KBNa_badge",
|
|
12032
|
+
"bulkActions": "F1KBNa_bulkActions",
|
|
12033
|
+
"expand": "F1KBNa_expand",
|
|
12034
|
+
"group": "F1KBNa_group",
|
|
12035
|
+
"rowHead": "F1KBNa_rowHead",
|
|
12010
12036
|
"settingsSelectorChevron": "F1KBNa_settingsSelectorChevron",
|
|
12037
|
+
"settingsRow": "F1KBNa_settingsRow",
|
|
12038
|
+
"panel": "F1KBNa_panel",
|
|
12011
12039
|
"detail": "F1KBNa_detail",
|
|
12012
|
-
"
|
|
12013
|
-
"
|
|
12014
|
-
"searchInput": "F1KBNa_searchInput",
|
|
12015
|
-
"searchCount": "F1KBNa_searchCount",
|
|
12016
|
-
"vSpacer": "F1KBNa_vSpacer",
|
|
12017
|
-
"code": "F1KBNa_code",
|
|
12018
|
-
"iconAction": "F1KBNa_iconAction",
|
|
12019
|
-
"kindHint": "F1KBNa_kindHint",
|
|
12020
|
-
"splitHScroll": "F1KBNa_splitHScroll",
|
|
12021
|
-
"overviewMarker": "F1KBNa_overviewMarker",
|
|
12022
|
-
"rail": "F1KBNa_rail",
|
|
12023
|
-
"wrap": "F1KBNa_wrap",
|
|
12024
|
-
"splitRdel": "F1KBNa_splitRdel",
|
|
12025
|
-
"close": "F1KBNa_close",
|
|
12026
|
-
"rows": "F1KBNa_rows",
|
|
12040
|
+
"split": "F1KBNa_split",
|
|
12041
|
+
"importNote": "F1KBNa_importNote",
|
|
12027
12042
|
"resizeHandle": "F1KBNa_resizeHandle",
|
|
12028
|
-
"
|
|
12029
|
-
"
|
|
12030
|
-
"
|
|
12031
|
-
"
|
|
12032
|
-
"
|
|
12033
|
-
"
|
|
12034
|
-
"
|
|
12035
|
-
"splitCol": "F1KBNa_splitCol",
|
|
12036
|
-
"overviewRuler": "F1KBNa_overviewRuler",
|
|
12037
|
-
"settingsSelector": "F1KBNa_settingsSelector",
|
|
12038
|
-
"badgeCount": "F1KBNa_badgeCount",
|
|
12039
|
-
"confirmActions": "F1KBNa_confirmActions",
|
|
12040
|
-
"row": "F1KBNa_row",
|
|
12041
|
-
"rowMeta": "F1KBNa_rowMeta",
|
|
12042
|
-
"settingsRowDesc": "F1KBNa_settingsRowDesc",
|
|
12043
|
-
"diffStats": "F1KBNa_diffStats",
|
|
12044
|
-
"splitRoot": "F1KBNa_splitRoot",
|
|
12045
|
-
"actionPrimary": "F1KBNa_actionPrimary",
|
|
12046
|
-
"lines": "F1KBNa_lines",
|
|
12043
|
+
"diff": "F1KBNa_diff",
|
|
12044
|
+
"blockActions": "F1KBNa_blockActions",
|
|
12045
|
+
"confirmText": "F1KBNa_confirmText",
|
|
12046
|
+
"vSpacer": "F1KBNa_vSpacer",
|
|
12047
|
+
"gutter": "F1KBNa_gutter",
|
|
12048
|
+
"states": "F1KBNa_states",
|
|
12049
|
+
"markerDel": "F1KBNa_markerDel",
|
|
12047
12050
|
"context": "F1KBNa_context",
|
|
12048
|
-
"footerButtons": "F1KBNa_footerButtons",
|
|
12049
|
-
"confirmBackdrop": "F1KBNa_confirmBackdrop",
|
|
12050
12051
|
"diffBodySplit": "F1KBNa_diffBodySplit",
|
|
12051
|
-
"
|
|
12052
|
-
"
|
|
12053
|
-
"
|
|
12054
|
-
"
|
|
12055
|
-
"
|
|
12056
|
-
"
|
|
12057
|
-
"noticeButton": "F1KBNa_noticeButton"
|
|
12052
|
+
"diffBodyWrap": "F1KBNa_diffBodyWrap",
|
|
12053
|
+
"subline": "F1KBNa_subline",
|
|
12054
|
+
"splitHScrollFill": "F1KBNa_splitHScrollFill",
|
|
12055
|
+
"settingsRowDesc": "F1KBNa_settingsRowDesc",
|
|
12056
|
+
"headerActions": "F1KBNa_headerActions",
|
|
12057
|
+
"badgeCount": "F1KBNa_badgeCount"
|
|
12058
12058
|
};
|
|
12059
12059
|
//#endregion
|
|
12060
12060
|
//#region lib/types/client/PendingPanel.js
|
|
@@ -12080,7 +12080,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12080
12080
|
/** Interactive composer/approval cards; clicking these keeps the panel open.
|
|
12081
12081
|
Deliberately the cards themselves, not the seat: the approval frame's wide
|
|
12082
12082
|
side gutters are blank space, so a click there must still close. */
|
|
12083
|
-
const KEEP_OPEN_SELECTOR = "[data-composer-card],[data-question-key] > *,[data-plan-review-key] > *";
|
|
12083
|
+
const KEEP_OPEN_SELECTOR = "[data-composer-card],[data-question-key] > *,[data-plan-review-key] > *,[data-approval-key] > *";
|
|
12084
12084
|
/** Seat counts as docked when its bottom is this close to the window bottom. */
|
|
12085
12085
|
const DOCKED_TOLERANCE_PX = 48;
|
|
12086
12086
|
/** File-list pane width bounds for the manual split drag, in px. */
|
|
@@ -12473,7 +12473,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12473
12473
|
});
|
|
12474
12474
|
}
|
|
12475
12475
|
/** The two-column (side-by-side) whole-file diff view. */
|
|
12476
|
-
const SplitDiff = (0, react.forwardRef)(function SplitDiff({ file, model, runs, langWrap, tabWidthSpaces, busy, t, onBlockKeep, onBlockRevert }, ref) {
|
|
12476
|
+
const SplitDiff = (0, react.forwardRef)(function SplitDiff({ file, model, runs, langWrap, tabWidthSpaces, busy, t, selection, onBlockKeep, onBlockRevert }, ref) {
|
|
12477
12477
|
const { pairs, pairOfRow } = (0, react.useMemo)(() => computeSideBySideDiff(model.diff.rows), [model]);
|
|
12478
12478
|
const pairCount = pairs.length;
|
|
12479
12479
|
const bodyRef = (0, react.useRef)(null);
|
|
@@ -12661,8 +12661,12 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12661
12661
|
return lo;
|
|
12662
12662
|
};
|
|
12663
12663
|
const viewport = viewportH > 0 ? viewportH : totalHeight;
|
|
12664
|
-
|
|
12665
|
-
|
|
12664
|
+
let start = Math.max(0, pairAtY(scrollTop) - OVERSCAN_ROWS);
|
|
12665
|
+
let end = Math.min(pairCount, pairAtY(scrollTop + viewport) + OVERSCAN_ROWS);
|
|
12666
|
+
if (selection !== void 0) {
|
|
12667
|
+
start = Math.min(start, selection.start);
|
|
12668
|
+
end = Math.max(end, selection.end + 1);
|
|
12669
|
+
}
|
|
12666
12670
|
const visiblePairs = pairs.slice(start, end);
|
|
12667
12671
|
const jump = (direction) => {
|
|
12668
12672
|
if (blockOfPair.length === 0) return;
|
|
@@ -13360,8 +13364,12 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13360
13364
|
return lo;
|
|
13361
13365
|
};
|
|
13362
13366
|
const viewport = viewportHeight > 0 ? viewportHeight : totalHeight;
|
|
13363
|
-
|
|
13364
|
-
|
|
13367
|
+
let start = Math.max(0, rowAtY(scrollTop) - OVERSCAN_ROWS);
|
|
13368
|
+
let end = Math.min(rowCount, rowAtY(scrollTop + viewport) + OVERSCAN_ROWS);
|
|
13369
|
+
if (selection !== void 0) {
|
|
13370
|
+
start = Math.min(start, selection.start);
|
|
13371
|
+
end = Math.max(end, selection.end + 1);
|
|
13372
|
+
}
|
|
13365
13373
|
const visibleRows = rows.slice(start, end);
|
|
13366
13374
|
const blockEnd = hoveredBlock === void 0 ? void 0 : model.blocks[hoveredBlock]?.end;
|
|
13367
13375
|
const blockActionsTop = blockEnd === void 0 ? 0 : Math.min(offsetOf(blockEnd + 1), Math.max(0, totalHeight - BLOCK_ACTIONS_FRAME_PX));
|
|
@@ -13743,6 +13751,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13743
13751
|
tabWidthSpaces,
|
|
13744
13752
|
busy,
|
|
13745
13753
|
t,
|
|
13754
|
+
selection,
|
|
13746
13755
|
onBlockKeep,
|
|
13747
13756
|
onBlockRevert
|
|
13748
13757
|
}) : (0, react_jsx_runtime.jsxs)("div", {
|
package/lib/index.js
CHANGED
|
@@ -912,7 +912,7 @@ function apply(ctx, config) {
|
|
|
912
912
|
sessionIds: [sessionId]
|
|
913
913
|
};
|
|
914
914
|
await ensureLoaded();
|
|
915
|
-
if (store.fold(entry))
|
|
915
|
+
if (store.fold(entry)) persistSession();
|
|
916
916
|
}
|
|
917
917
|
/** The stable `FsError.code`, when the thrown value carries one. */
|
|
918
918
|
function fsErrorCodeOf(error) {
|
|
@@ -998,13 +998,13 @@ function apply(ctx, config) {
|
|
|
998
998
|
entry: void 0,
|
|
999
999
|
fileText: void 0
|
|
1000
1000
|
});
|
|
1001
|
-
|
|
1001
|
+
persistSession();
|
|
1002
1002
|
continue;
|
|
1003
1003
|
}
|
|
1004
1004
|
if (live.kind === "unavailable") {
|
|
1005
1005
|
store.remove(entry.path);
|
|
1006
1006
|
purgeForEntry(entry.path);
|
|
1007
|
-
|
|
1007
|
+
persistSession();
|
|
1008
1008
|
continue;
|
|
1009
1009
|
}
|
|
1010
1010
|
const content = live.content;
|
|
@@ -1030,7 +1030,7 @@ function apply(ctx, config) {
|
|
|
1030
1030
|
},
|
|
1031
1031
|
fileText: content
|
|
1032
1032
|
});
|
|
1033
|
-
|
|
1033
|
+
persistSession();
|
|
1034
1034
|
if (redoWasPresent) redoCleared = true;
|
|
1035
1035
|
}
|
|
1036
1036
|
const state = {
|
|
@@ -1135,14 +1135,47 @@ function apply(ctx, config) {
|
|
|
1135
1135
|
* file.
|
|
1136
1136
|
* @returns resolution after the write settles (successful or logged).
|
|
1137
1137
|
*/
|
|
1138
|
-
|
|
1139
|
-
|
|
1138
|
+
const PERSIST_THROTTLE_MS = 1e3;
|
|
1139
|
+
let persistDirty = false;
|
|
1140
|
+
let persistScheduled = false;
|
|
1141
|
+
let lastPersistAt = 0;
|
|
1142
|
+
let persistTimer;
|
|
1143
|
+
/** Actually write the (dirty) store to disk; one coalesced write. */
|
|
1144
|
+
async function flushPersist() {
|
|
1145
|
+
if (!persistDirty) return;
|
|
1146
|
+
persistDirty = false;
|
|
1147
|
+
lastPersistAt = Date.now();
|
|
1140
1148
|
try {
|
|
1149
|
+
await ensureLoaded();
|
|
1141
1150
|
await persistence.save(store.all());
|
|
1142
1151
|
} catch (error) {
|
|
1143
1152
|
ctx.logger.warn(`diff-approval: persisting pending changes failed: ${errorMessage(error)}`);
|
|
1144
1153
|
}
|
|
1145
1154
|
}
|
|
1155
|
+
/** Mark the store dirty and schedule one throttled, coalesced write. Pass
|
|
1156
|
+
* `force` to write immediately (user actions need durable, immediate results). */
|
|
1157
|
+
function persistSession(force = false) {
|
|
1158
|
+
persistDirty = true;
|
|
1159
|
+
if (force) {
|
|
1160
|
+
if (persistScheduled) {
|
|
1161
|
+
clearTimeout(persistTimer);
|
|
1162
|
+
persistScheduled = false;
|
|
1163
|
+
}
|
|
1164
|
+
flushPersist();
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
if (persistScheduled) return;
|
|
1168
|
+
const delay = PERSIST_THROTTLE_MS - (Date.now() - lastPersistAt);
|
|
1169
|
+
if (delay <= 0) flushPersist();
|
|
1170
|
+
else {
|
|
1171
|
+
persistScheduled = true;
|
|
1172
|
+
persistTimer = setTimeout(() => {
|
|
1173
|
+
persistScheduled = false;
|
|
1174
|
+
flushPersist();
|
|
1175
|
+
}, delay);
|
|
1176
|
+
persistTimer.unref?.();
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1146
1179
|
ctx.on("tools/result", (exec, result) => {
|
|
1147
1180
|
if (exec.name === "str_replace_editor") {
|
|
1148
1181
|
captureEditorMutation(exec, result);
|
|
@@ -1201,7 +1234,7 @@ function apply(ctx, config) {
|
|
|
1201
1234
|
entry: void 0,
|
|
1202
1235
|
fileText: void 0
|
|
1203
1236
|
});
|
|
1204
|
-
|
|
1237
|
+
persistSession(true);
|
|
1205
1238
|
return {
|
|
1206
1239
|
ok: true,
|
|
1207
1240
|
value: { outcome: "kept" }
|
|
@@ -1247,7 +1280,7 @@ function apply(ctx, config) {
|
|
|
1247
1280
|
}
|
|
1248
1281
|
store.remove(target.id);
|
|
1249
1282
|
if (undo !== void 0) pushUndo(target.sessionId, undo.before, undo.after);
|
|
1250
|
-
|
|
1283
|
+
persistSession(true);
|
|
1251
1284
|
return {
|
|
1252
1285
|
ok: true,
|
|
1253
1286
|
value: { outcome: "reverted" }
|
|
@@ -1281,7 +1314,7 @@ function apply(ctx, config) {
|
|
|
1281
1314
|
entry: afterEntry,
|
|
1282
1315
|
fileText: void 0
|
|
1283
1316
|
});
|
|
1284
|
-
|
|
1317
|
+
persistSession();
|
|
1285
1318
|
return {
|
|
1286
1319
|
ok: true,
|
|
1287
1320
|
value: updatedOld === entry.newText ? {
|
|
@@ -1334,7 +1367,7 @@ function apply(ctx, config) {
|
|
|
1334
1367
|
return rpcError(`block revert failed: ${errorMessage(error)}`);
|
|
1335
1368
|
}
|
|
1336
1369
|
if (undo !== void 0) pushUndo(blockTarget.sessionId, undo.before, undo.after);
|
|
1337
|
-
|
|
1370
|
+
persistSession();
|
|
1338
1371
|
return {
|
|
1339
1372
|
ok: true,
|
|
1340
1373
|
value: normalizeEol(updatedNew) === normalizeEol(entry.oldText) ? {
|
|
@@ -1358,7 +1391,7 @@ function apply(ctx, config) {
|
|
|
1358
1391
|
return rpcError(`undo failed: ${errorMessage(error)}`);
|
|
1359
1392
|
}
|
|
1360
1393
|
redoStack.push(pair);
|
|
1361
|
-
|
|
1394
|
+
persistSession(true);
|
|
1362
1395
|
return {
|
|
1363
1396
|
ok: true,
|
|
1364
1397
|
value: {
|
|
@@ -1382,7 +1415,7 @@ function apply(ctx, config) {
|
|
|
1382
1415
|
return rpcError(`redo failed: ${errorMessage(error)}`);
|
|
1383
1416
|
}
|
|
1384
1417
|
undoStack.push(pair);
|
|
1385
|
-
|
|
1418
|
+
persistSession(true);
|
|
1386
1419
|
return {
|
|
1387
1420
|
ok: true,
|
|
1388
1421
|
value: {
|
|
@@ -1443,7 +1476,7 @@ function apply(ctx, config) {
|
|
|
1443
1476
|
}
|
|
1444
1477
|
}
|
|
1445
1478
|
if (imported > 0) {
|
|
1446
|
-
|
|
1479
|
+
persistSession();
|
|
1447
1480
|
const after = new Map(store.list(sessionId).map((entry) => [entry.path, entry]));
|
|
1448
1481
|
const batchBefore = [];
|
|
1449
1482
|
const batchAfter = [];
|
|
@@ -41,6 +41,14 @@ interface ChangeBlock {
|
|
|
41
41
|
start: number;
|
|
42
42
|
end: number;
|
|
43
43
|
}
|
|
44
|
+
/** One selected line range in row indices, normalized low-to-high. */
|
|
45
|
+
interface RowRange {
|
|
46
|
+
start: number;
|
|
47
|
+
end: number;
|
|
48
|
+
/** Which file's lines a split selection references: 'old' (left column), 'new'
|
|
49
|
+
* (right column); undefined in single column (always the new file). */
|
|
50
|
+
side?: 'old' | 'new';
|
|
51
|
+
}
|
|
44
52
|
/** Imperative surface the parent uses to drive block navigation from the
|
|
45
53
|
* shared toolbar/keyboard in split mode (its own `focus` is private here). */
|
|
46
54
|
export interface SplitDiffHandle {
|
|
@@ -56,6 +64,7 @@ export declare const SplitDiff: import("react").ForwardRefExoticComponent<{
|
|
|
56
64
|
tabWidthSpaces: number;
|
|
57
65
|
busy: boolean;
|
|
58
66
|
t: Translator;
|
|
67
|
+
selection: RowRange | undefined;
|
|
59
68
|
onBlockKeep: (sessionId: SessionId, id: string, block: DiffApprovalBlockRange) => Promise<void>;
|
|
60
69
|
onBlockRevert: (sessionId: SessionId, id: string, block: DiffApprovalBlockRange) => Promise<void>;
|
|
61
70
|
} & import("react").RefAttributes<SplitDiffHandle>>;
|
package/package.json
CHANGED