dsh-diff-approval 0.24.1 → 0.26.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/lib/client.js +1078 -374
- package/lib/index.js +56 -20
- package/lib/types/client/PendingPanel.d.ts +24 -0
- package/lib/types/client/discussion.d.ts +68 -16
- package/lib/types/client/locales.d.ts +24 -6
- package/lib/types/client/panel-memory.d.ts +7 -0
- package/lib/types/client/port.d.ts +5 -2
- package/lib/types/client/settings.d.ts +13 -0
- package/lib/types/client/slots.d.ts +1 -1
- package/lib/types/client/store.d.ts +1 -1
- package/lib/types/types.d.ts +11 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -3021,6 +3021,58 @@ function apply(ctx, config) {
|
|
|
3021
3021
|
}
|
|
3022
3022
|
};
|
|
3023
3023
|
const isDirectory = info.type === "directory";
|
|
3024
|
+
if (target.exact && isDirectory) return {
|
|
3025
|
+
ok: true,
|
|
3026
|
+
value: {
|
|
3027
|
+
outcome: "not-a-file",
|
|
3028
|
+
added: 0,
|
|
3029
|
+
duplicates: 0
|
|
3030
|
+
}
|
|
3031
|
+
};
|
|
3032
|
+
/**
|
|
3033
|
+
* Admit what the add found and answer the wire value. Shared by the two ways in — the
|
|
3034
|
+
* one file a reader named, and the scan of a path — so a named file is listed, counted
|
|
3035
|
+
* and identified exactly like a scanned one.
|
|
3036
|
+
*
|
|
3037
|
+
* @param candidates - the entries to admit (already built, in order).
|
|
3038
|
+
* @param directory - whether the named path was a directory (its own outcome wording).
|
|
3039
|
+
* @param cut - whether the walk hit its cap.
|
|
3040
|
+
* @returns the channel's answer for this add.
|
|
3041
|
+
*/
|
|
3042
|
+
const admitNamed = async (candidates, directory, cut) => {
|
|
3043
|
+
const listed = new Set(store.list(target.sessionId).map((entry) => pathIdentity(entry.path)));
|
|
3044
|
+
const fresh = candidates.filter((entry) => !listed.has(pathIdentity(entry.path)));
|
|
3045
|
+
const duplicates = candidates.length - fresh.length;
|
|
3046
|
+
const added = await foldBatch(target.sessionId, fresh, true);
|
|
3047
|
+
const outcome = added > 0 ? "added" : duplicates > 0 ? "duplicate" : directory ? "empty" : "unchanged";
|
|
3048
|
+
const single = directory ? void 0 : fresh[0] ?? store.list(target.sessionId).find((entry) => pathIdentity(entry.path) === pathIdentity(absolute));
|
|
3049
|
+
return {
|
|
3050
|
+
ok: true,
|
|
3051
|
+
value: {
|
|
3052
|
+
outcome,
|
|
3053
|
+
added,
|
|
3054
|
+
duplicates,
|
|
3055
|
+
...single === void 0 ? {} : { id: single.id },
|
|
3056
|
+
...cut ? { truncated: true } : {}
|
|
3057
|
+
}
|
|
3058
|
+
};
|
|
3059
|
+
};
|
|
3060
|
+
const now = Date.now();
|
|
3061
|
+
if (target.exact) {
|
|
3062
|
+
const existing = store.list(target.sessionId).find((entry) => pathIdentity(entry.path) === pathIdentity(absolute));
|
|
3063
|
+
if (existing !== void 0) return await admitNamed([existing], false, false);
|
|
3064
|
+
const content = await readTextOrNone(absolute, signal);
|
|
3065
|
+
return await admitNamed(content === void 0 ? [] : [{
|
|
3066
|
+
id: absolute,
|
|
3067
|
+
sessionId: target.sessionId,
|
|
3068
|
+
path: absolute,
|
|
3069
|
+
kind: "edit",
|
|
3070
|
+
oldText: content,
|
|
3071
|
+
newText: content,
|
|
3072
|
+
updatedAt: now,
|
|
3073
|
+
sessionIds: [target.sessionId]
|
|
3074
|
+
}], false, false);
|
|
3075
|
+
}
|
|
3024
3076
|
const root = detectVcsRoot(workspace.path);
|
|
3025
3077
|
if (root === void 0) return {
|
|
3026
3078
|
ok: true,
|
|
@@ -3055,7 +3107,6 @@ function apply(ctx, config) {
|
|
|
3055
3107
|
}
|
|
3056
3108
|
};
|
|
3057
3109
|
}
|
|
3058
|
-
const now = Date.now();
|
|
3059
3110
|
const candidates = changes.map((change) => ({
|
|
3060
3111
|
id: change.path,
|
|
3061
3112
|
sessionId: target.sessionId,
|
|
@@ -3093,24 +3144,7 @@ function apply(ctx, config) {
|
|
|
3093
3144
|
});
|
|
3094
3145
|
}
|
|
3095
3146
|
}
|
|
3096
|
-
|
|
3097
|
-
const fresh = candidates.filter((entry) => !listed.has(pathIdentity(entry.path)));
|
|
3098
|
-
const duplicates = candidates.length - fresh.length;
|
|
3099
|
-
const added = await foldBatch(target.sessionId, fresh, true);
|
|
3100
|
-
const outcome = added > 0 ? "added" : duplicates > 0 ? "duplicate" : isDirectory ? "empty" : "unchanged";
|
|
3101
|
-
return {
|
|
3102
|
-
ok: true,
|
|
3103
|
-
value: truncated ? {
|
|
3104
|
-
outcome,
|
|
3105
|
-
added,
|
|
3106
|
-
duplicates,
|
|
3107
|
-
truncated
|
|
3108
|
-
} : {
|
|
3109
|
-
outcome,
|
|
3110
|
-
added,
|
|
3111
|
-
duplicates
|
|
3112
|
-
}
|
|
3113
|
-
};
|
|
3147
|
+
return await admitNamed(candidates, isDirectory, truncated);
|
|
3114
3148
|
}
|
|
3115
3149
|
case "open": {
|
|
3116
3150
|
const target = openTargetOf(payload);
|
|
@@ -3282,10 +3316,12 @@ function addTargetOf(payload) {
|
|
|
3282
3316
|
if (sessionId === void 0) return void 0;
|
|
3283
3317
|
const path = pathFieldOf(payload)?.trim();
|
|
3284
3318
|
if (path === void 0 || path === "") return void 0;
|
|
3319
|
+
const record = payload;
|
|
3285
3320
|
return {
|
|
3286
3321
|
sessionId,
|
|
3287
3322
|
path,
|
|
3288
|
-
includeUnchanged:
|
|
3323
|
+
includeUnchanged: record.includeUnchanged === true,
|
|
3324
|
+
exact: record.exact === true
|
|
3289
3325
|
};
|
|
3290
3326
|
}
|
|
3291
3327
|
/** Narrow a wire payload to one open target: the keep/revert pair plus the action. */
|
|
@@ -22,6 +22,30 @@ export declare function diffPathsMatch(chipPath: string, filePath: string, works
|
|
|
22
22
|
* breakpoint so the two stay consistent. */
|
|
23
23
|
export declare const SIDEBAR_AUTO_COLLAPSE_PX = 1024;
|
|
24
24
|
export declare function wrapInto(text: string, widthPx: number, measure: (t: string) => number, tabPx: number): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Wrap one line of a turn the way the browser lays it out: the prose by character, each inline-code
|
|
27
|
+
* chip as one box that cannot be broken.
|
|
28
|
+
*
|
|
29
|
+
* `wrapInto` walks characters and nothing else, which is right for the code view and wrong here:
|
|
30
|
+
* a turn's chip is an inline-flex box (the chat's own inline code, see `.discussionCode`), so half
|
|
31
|
+
* of a chip never lands on the next line — it moves over whole, and the text after it starts after
|
|
32
|
+
* the box rather than inside it. Measuring the chip as ordinary text therefore reserves the wrong
|
|
33
|
+
* number of rows on exactly the lines that carry one, and a row too few is a clipped last line.
|
|
34
|
+
*
|
|
35
|
+
* The prose segments are wrapped by `wrapInto` itself, so a line with a chip in it breaks its words
|
|
36
|
+
* and its spaces exactly where a line without one does; only the chips are placed as boxes.
|
|
37
|
+
*
|
|
38
|
+
* @param line - the line's text, markers and all: the runs are read the way the render reads them.
|
|
39
|
+
* @param room - the width the line wraps in.
|
|
40
|
+
* @param measure - the prose measurer.
|
|
41
|
+
* @param chipWidth - the width of one chip's BOX (its text in the chip's own font, plus its padding
|
|
42
|
+
* and its hairline).
|
|
43
|
+
* @param tabPx - one tab stop, in px.
|
|
44
|
+
* @returns the row count for the line.
|
|
45
|
+
*/
|
|
46
|
+
export declare function wrapChipRows(line: string, room: number, measure: (text: string) => number, chipWidth: (text: string) => number, tabPx: number): number;
|
|
47
|
+
/** Create a measurer bound to `font`; falls back to a rough char estimate. */
|
|
48
|
+
export declare function makeMeasurer(font: string | undefined): ((text: string) => number) | undefined;
|
|
25
49
|
/** Full panel props composed by the sidebar footer-action slot. */
|
|
26
50
|
export type PendingPanelProps = PropsRuntime<'sidebar.footer.action'> & InjectFace<PendingPanelFace> & PropsLocale<'diff-approval'> & PendingPanelDockProps;
|
|
27
51
|
/** How the panel is hosted when it is not the footer's floating overlay: the
|
|
@@ -37,6 +37,14 @@ export interface DiscussionQuoteLine {
|
|
|
37
37
|
old: number | undefined;
|
|
38
38
|
/** New-file number — the second gutter — `undefined` on a removed line. */
|
|
39
39
|
new: number | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Which side of the change the row was on when the thread quoted it: an added line, a removed
|
|
42
|
+
* one, or context. Kept so the quote can wear the diff's own green/red washes — the reader
|
|
43
|
+
* recognised those rows by their colour, and a quote that renders them as plain code loses the
|
|
44
|
+
* thing they were looking at. Absent on a thread quoted before this was recorded, which then
|
|
45
|
+
* simply draws no wash.
|
|
46
|
+
*/
|
|
47
|
+
kind?: 'add' | 'del' | 'context';
|
|
40
48
|
}
|
|
41
49
|
/** One discussion bound to a row range. */
|
|
42
50
|
export interface Discussion {
|
|
@@ -105,7 +113,9 @@ export interface Discussion {
|
|
|
105
113
|
/**
|
|
106
114
|
* How many rows the block's body occupies, measured by the caller from what it
|
|
107
115
|
* actually renders (the thread plus the compose row). It is what keeps a
|
|
108
|
-
* discussion block's height an exact multiple of the
|
|
116
|
+
* discussion block's height an exact multiple of the thread's own row — which is fixed, not
|
|
117
|
+
* the code's (see `THREAD_ROW_PX`): a thread is prose and keeps its size whatever the reader
|
|
118
|
+
* sets the code's line height to.
|
|
109
119
|
*/
|
|
110
120
|
bodyRows?: number;
|
|
111
121
|
/** How many older messages the row cap left out of the render. */
|
|
@@ -113,32 +123,58 @@ export interface Discussion {
|
|
|
113
123
|
}
|
|
114
124
|
/** Rows a folded block occupies: its header line. */
|
|
115
125
|
export declare const DISCUSSION_HEADER_ROWS = 1;
|
|
116
|
-
/** Rows the compose area occupies: 0.3 + 1.4 + 0.3 of
|
|
126
|
+
/** Rows the compose area occupies: 0.3 + 1.4 + 0.3 of the thread's own row. */
|
|
117
127
|
export declare const DISCUSSION_COMPOSE_ROWS = 2;
|
|
118
128
|
/**
|
|
119
|
-
* The
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
*
|
|
127
|
-
* A thread grows without bound, so the block shows its tail and says what it is
|
|
128
|
-
* hiding rather than clipping silently; the hidden note costs one row of the
|
|
129
|
-
* budget itself. Sizes are in whatever unit the caller budgets in (the panel uses
|
|
130
|
-
* code rows, fractions included, and rounds the total up once).
|
|
129
|
+
* The newest rounds of a thread, and how many older turns were left out.
|
|
130
|
+
*
|
|
131
|
+
* A thread grows without bound, so the block shows its tail and says what it is hiding. The unit
|
|
132
|
+
* is the round rather than a row budget: a block keeps the last `rounds` questions and
|
|
133
|
+
* everything said after them, however long those turns are (the count is a preference). That is possible
|
|
134
|
+
* because the block reserves exactly what it draws (see `discussionRows`), so a long answer is
|
|
135
|
+
* shown in full instead of being sliced — the row budget this replaces existed to stop an old
|
|
136
|
+
* thread from swamping the diff, and a round cap does that without ever cutting a turn in half.
|
|
131
137
|
*
|
|
132
138
|
* @param messages - the whole thread, oldest first.
|
|
139
|
+
* @param rounds - how many rounds to keep (at least one: something has to be visible).
|
|
133
140
|
* @param sizeOf - the size one message needs when rendered (text plus its chrome).
|
|
134
|
-
* @param capRows - the body budget.
|
|
135
141
|
* @returns the messages to render, the count left out, and the size they need.
|
|
136
142
|
*/
|
|
137
|
-
export declare function
|
|
143
|
+
export declare function discussionRounds(messages: readonly DiscussionMessage[], rounds: number, sizeOf: (message: DiscussionMessage) => number): {
|
|
138
144
|
messages: readonly DiscussionMessage[];
|
|
139
145
|
hidden: number;
|
|
140
146
|
rows: number;
|
|
141
147
|
};
|
|
148
|
+
/** One run of a turn's prose, after its inline Markdown is read. */
|
|
149
|
+
export interface DiscussionRun {
|
|
150
|
+
/** A literal run, inline `code`, or **strong** emphasis. */
|
|
151
|
+
kind: 'text' | 'code' | 'strong';
|
|
152
|
+
/** What the run draws: for `code` and `strong`, the text with its markers gone. */
|
|
153
|
+
text: string;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Read one turn's inline Markdown: `code` and **strong**.
|
|
157
|
+
*
|
|
158
|
+
* Deliberately tiny. The thread is laid out on the diff's own row grid — one line box per code
|
|
159
|
+
* row — so nothing here may become a block: no headings, lists, quotes or fenced code. A marker
|
|
160
|
+
* with no partner, or one spanning a line break, is left exactly as typed, and so is everything
|
|
161
|
+
* this does not know about.
|
|
162
|
+
*
|
|
163
|
+
* @param text - the turn's text.
|
|
164
|
+
* @returns its runs, in order.
|
|
165
|
+
*/
|
|
166
|
+
export declare function discussionRuns(text: string): DiscussionRun[];
|
|
167
|
+
/**
|
|
168
|
+
* A turn's text with its inline markers gone: what the runs draw, character for character.
|
|
169
|
+
*
|
|
170
|
+
* The row measurement uses this, so the rows a block reserves and the text it draws agree. The
|
|
171
|
+
* markers are not drawn, and counting them would reserve room for characters nobody sees — which
|
|
172
|
+
* is exactly the kind of whole-row slack that leaves a blank row in the block.
|
|
173
|
+
*
|
|
174
|
+
* @param text - the turn's text.
|
|
175
|
+
* @returns the same text without its `code` and **strong** markers.
|
|
176
|
+
*/
|
|
177
|
+
export declare function discussionPlainText(text: string): string;
|
|
142
178
|
/**
|
|
143
179
|
* An answer with its blank lines dropped.
|
|
144
180
|
*
|
|
@@ -228,6 +264,22 @@ export declare function discussionOverlapping(discussions: readonly Discussion[]
|
|
|
228
264
|
* @returns the re-anchored discussion (the same object when nothing moved).
|
|
229
265
|
*/
|
|
230
266
|
export declare function remapDiscussion(discussion: Discussion, lineOf: (row: number) => number | undefined, textOf: (row: number) => string, rowCount: number): Discussion;
|
|
267
|
+
/**
|
|
268
|
+
* Re-anchor a whole file's blocks in one pass.
|
|
269
|
+
*
|
|
270
|
+
* Each block is re-anchored exactly as `remapDiscussion` does it — same rules, same identities,
|
|
271
|
+
* same "nothing moved, same object back" contract — but the row windows every quote is looked up
|
|
272
|
+
* in are joined ONCE for the whole list. A rebuild (a keep, an edit, a switched file) runs this
|
|
273
|
+
* over every block a file has, and joining the rows per block is what made the pass cost grow with
|
|
274
|
+
* the number of comments on a long file.
|
|
275
|
+
*
|
|
276
|
+
* @param discussions - the blocks to re-anchor.
|
|
277
|
+
* @param lineOf - the new-file line number of a row, or `undefined` for a row that has none.
|
|
278
|
+
* @param textOf - the text of a row, for the quote comparison.
|
|
279
|
+
* @param rowCount - how many rows the current model has.
|
|
280
|
+
* @returns the re-anchored blocks, in the order they came in.
|
|
281
|
+
*/
|
|
282
|
+
export declare function remapDiscussions(discussions: readonly Discussion[], lineOf: (row: number) => number | undefined, textOf: (row: number) => string, rowCount: number): readonly Discussion[];
|
|
231
283
|
/** What the selection frame shows for the current selection. */
|
|
232
284
|
export interface SelectionFrameActions {
|
|
233
285
|
/** Whether keep/revert apply (the selection fully covers change blocks). */
|
|
@@ -11,6 +11,12 @@ export declare const zh: {
|
|
|
11
11
|
'panel.readFailed': string;
|
|
12
12
|
'panel.group.current': string;
|
|
13
13
|
'panel.group.others': string;
|
|
14
|
+
'panel.tabs': string;
|
|
15
|
+
'panel.tab.pending': string;
|
|
16
|
+
'panel.tab.comments': string;
|
|
17
|
+
'panel.commentsEmpty': string;
|
|
18
|
+
'panel.commentOutdated': string;
|
|
19
|
+
'panel.commentEmptyTitle': string;
|
|
14
20
|
'panel.aria': string;
|
|
15
21
|
'panel.stats': string;
|
|
16
22
|
'panel.blockPosition': string;
|
|
@@ -50,10 +56,14 @@ export declare const zh: {
|
|
|
50
56
|
'panel.quickSummon': string;
|
|
51
57
|
'panel.commentMode': string;
|
|
52
58
|
'panel.commentModeDesc': string;
|
|
59
|
+
'panel.discussionRounds': string;
|
|
60
|
+
'panel.discussionRoundsDesc': string;
|
|
53
61
|
'panel.quickSummonDesc': string;
|
|
54
62
|
'panel.recordShortcut': string;
|
|
55
63
|
'settings.keybindings': string;
|
|
56
64
|
'settings.keybindingsDesc': string;
|
|
65
|
+
'settings.comment': string;
|
|
66
|
+
'settings.commentDesc': string;
|
|
57
67
|
'settings.diffView': string;
|
|
58
68
|
'settings.diffViewDesc': string;
|
|
59
69
|
'settings.diffPreview': string;
|
|
@@ -89,14 +99,12 @@ export declare const zh: {
|
|
|
89
99
|
'action.discussionExpand': string;
|
|
90
100
|
'action.discussionCollapse': string;
|
|
91
101
|
'discussion.placeholder': string;
|
|
92
|
-
'discussion.placeholderOutdated': string;
|
|
93
102
|
'discussion.marker': string;
|
|
94
103
|
'discussion.promptRule': string;
|
|
95
104
|
'discussion.promptRuleSkill': string;
|
|
96
105
|
'discussion.thinking': string;
|
|
97
106
|
'discussion.queued': string;
|
|
98
|
-
'discussion.
|
|
99
|
-
'discussion.quote': string;
|
|
107
|
+
'discussion.outdatedQuote': string;
|
|
100
108
|
'discussion.hidden': string;
|
|
101
109
|
'discussion.failed': string;
|
|
102
110
|
'discussion.stopped': string;
|
|
@@ -106,6 +114,7 @@ export declare const zh: {
|
|
|
106
114
|
'action.keepAll': string;
|
|
107
115
|
'action.revertAll': string;
|
|
108
116
|
'action.openFile': string;
|
|
117
|
+
'action.pathField': string;
|
|
109
118
|
'action.revealFile': string;
|
|
110
119
|
'action.busy': string;
|
|
111
120
|
'action.prevDiff': string;
|
|
@@ -226,6 +235,12 @@ export declare const en: {
|
|
|
226
235
|
'panel.readFailed': string;
|
|
227
236
|
'panel.group.current': string;
|
|
228
237
|
'panel.group.others': string;
|
|
238
|
+
'panel.tabs': string;
|
|
239
|
+
'panel.tab.pending': string;
|
|
240
|
+
'panel.tab.comments': string;
|
|
241
|
+
'panel.commentsEmpty': string;
|
|
242
|
+
'panel.commentOutdated': string;
|
|
243
|
+
'panel.commentEmptyTitle': string;
|
|
229
244
|
'panel.aria': string;
|
|
230
245
|
'panel.stats': string;
|
|
231
246
|
'panel.blockPosition': string;
|
|
@@ -265,10 +280,14 @@ export declare const en: {
|
|
|
265
280
|
'panel.quickSummon': string;
|
|
266
281
|
'panel.commentMode': string;
|
|
267
282
|
'panel.commentModeDesc': string;
|
|
283
|
+
'panel.discussionRounds': string;
|
|
284
|
+
'panel.discussionRoundsDesc': string;
|
|
268
285
|
'panel.quickSummonDesc': string;
|
|
269
286
|
'panel.recordShortcut': string;
|
|
270
287
|
'settings.keybindings': string;
|
|
271
288
|
'settings.keybindingsDesc': string;
|
|
289
|
+
'settings.comment': string;
|
|
290
|
+
'settings.commentDesc': string;
|
|
272
291
|
'settings.diffView': string;
|
|
273
292
|
'settings.diffViewDesc': string;
|
|
274
293
|
'settings.diffPreview': string;
|
|
@@ -304,14 +323,12 @@ export declare const en: {
|
|
|
304
323
|
'action.discussionExpand': string;
|
|
305
324
|
'action.discussionCollapse': string;
|
|
306
325
|
'discussion.placeholder': string;
|
|
307
|
-
'discussion.placeholderOutdated': string;
|
|
308
326
|
'discussion.marker': string;
|
|
309
327
|
'discussion.promptRule': string;
|
|
310
328
|
'discussion.promptRuleSkill': string;
|
|
311
329
|
'discussion.thinking': string;
|
|
312
330
|
'discussion.queued': string;
|
|
313
|
-
'discussion.
|
|
314
|
-
'discussion.quote': string;
|
|
331
|
+
'discussion.outdatedQuote': string;
|
|
315
332
|
'discussion.hidden': string;
|
|
316
333
|
'discussion.failed': string;
|
|
317
334
|
'discussion.stopped': string;
|
|
@@ -321,6 +338,7 @@ export declare const en: {
|
|
|
321
338
|
'action.keepAll': string;
|
|
322
339
|
'action.revertAll': string;
|
|
323
340
|
'action.openFile': string;
|
|
341
|
+
'action.pathField': string;
|
|
324
342
|
'action.revealFile': string;
|
|
325
343
|
'action.busy': string;
|
|
326
344
|
'action.prevDiff': string;
|
|
@@ -14,6 +14,13 @@
|
|
|
14
14
|
* @module dsh-diff-approval/client/panel-memory
|
|
15
15
|
*/
|
|
16
16
|
import type { Discussion } from './discussion.ts';
|
|
17
|
+
/**
|
|
18
|
+
* Fired on `window` whenever a session's threads change. The threads are written by the file
|
|
19
|
+
* detail (which owns them) and read by the list pane (whose comments tab shows them all), so the
|
|
20
|
+
* event is what keeps the two in step: a reader who posts a comment sees it in the list at once
|
|
21
|
+
* instead of on the next poll.
|
|
22
|
+
*/
|
|
23
|
+
export declare const COMMENTS_CHANGED_EVENT = "dsh-diff-approval:comments-changed";
|
|
17
24
|
/**
|
|
18
25
|
* The comment threads a session's panel is holding.
|
|
19
26
|
* @param sessionId - the session, if any.
|
|
@@ -30,8 +30,11 @@ export interface DiffApprovalPort {
|
|
|
30
30
|
refreshVcs(sessionId: SessionId, id: string, includeUntracked: boolean): Promise<DiffApprovalRefreshValue>;
|
|
31
31
|
/** List one workspace directory level (workspace-relative; `''` is the root). */
|
|
32
32
|
browse(sessionId: SessionId, path?: string): Promise<DiffApprovalBrowseValue>;
|
|
33
|
-
/**
|
|
34
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Add one named path (a file, or a directory's whole subtree) to the list. With `exact`, the
|
|
35
|
+
* path must be one regular file: a directory is refused instead of being scanned.
|
|
36
|
+
*/
|
|
37
|
+
addPath(sessionId: SessionId, path: string, includeUnchanged: boolean, exact?: boolean): Promise<DiffApprovalAddValue>;
|
|
35
38
|
/** Open one file with its default application or reveal it in the folder. */
|
|
36
39
|
open(sessionId: SessionId, id: string, action: DiffApprovalOpenAction): Promise<DiffApprovalOpenValue>;
|
|
37
40
|
/** Keep every pending entry of one session in a single host call (one batch). */
|
|
@@ -20,6 +20,12 @@ export interface DiffApprovalCover {
|
|
|
20
20
|
* composer. */
|
|
21
21
|
export declare const FLOAT_COVER_DEFAULT: DiffApprovalCover;
|
|
22
22
|
/** Default lead rows above a jumped-to diff block (kept small and bounded). */
|
|
23
|
+
/** Rounds of a comment thread a block keeps before it hides the older ones. A round is one
|
|
24
|
+
* question and the answer to it. One is the floor (something has to be visible) and the
|
|
25
|
+
* ceiling keeps a long thread from swamping the diff it annotates. */
|
|
26
|
+
export declare const DISCUSSION_ROUNDS_DEFAULT = 2;
|
|
27
|
+
export declare const DISCUSSION_ROUNDS_MIN = 1;
|
|
28
|
+
export declare const DISCUSSION_ROUNDS_MAX = 10;
|
|
23
29
|
export declare const NAV_LEAD_ROWS_DEFAULT = 2;
|
|
24
30
|
export declare const NAV_LEAD_ROWS_MIN = 0;
|
|
25
31
|
export declare const NAV_LEAD_ROWS_MAX = 10;
|
|
@@ -227,6 +233,13 @@ export declare function setMdMaxWidth(value: number): void;
|
|
|
227
233
|
* @returns the lead row count.
|
|
228
234
|
*/
|
|
229
235
|
export declare function navLeadRows(): number;
|
|
236
|
+
/**
|
|
237
|
+
* How many rounds of a comment thread the panel keeps.
|
|
238
|
+
* @returns the configured round count, or the default when nothing valid is stored.
|
|
239
|
+
*/
|
|
240
|
+
export declare function discussionRoundLimit(): number;
|
|
241
|
+
/** Persist the comment thread's round limit. */
|
|
242
|
+
export declare function setDiscussionRoundLimit(value: number): void;
|
|
230
243
|
/** Persist the block-jump lead row count. */
|
|
231
244
|
export declare function setNavLeadRows(value: number): void;
|
|
232
245
|
/** Default quick-summon chord (toggle the review panel open/closed). */
|
|
@@ -90,7 +90,7 @@ export interface PendingPanelFace {
|
|
|
90
90
|
/** List one workspace directory level for the add-path dialog. */
|
|
91
91
|
onBrowse: (sessionId: SessionId, path?: string) => Promise<DiffApprovalBrowseValue>;
|
|
92
92
|
/** Add one named path (a file, or a directory's whole subtree) to the list. */
|
|
93
|
-
onAddPath: (sessionId: SessionId, path: string, includeUnchanged: boolean) => Promise<DiffApprovalAddValue>;
|
|
93
|
+
onAddPath: (sessionId: SessionId, path: string, includeUnchanged: boolean, exact?: boolean) => Promise<DiffApprovalAddValue>;
|
|
94
94
|
/** Keep every pending entry of one session in a single host call (bulk). */
|
|
95
95
|
onKeepAll: (sessionId: SessionId) => Promise<void>;
|
|
96
96
|
/** Revert every pending entry of one session in a single host call (bulk). */
|
|
@@ -34,7 +34,7 @@ export interface PendingDiffStore extends HostObservable<PendingDiffSnapshot> {
|
|
|
34
34
|
/** List one workspace directory level for the add-path dialog. */
|
|
35
35
|
browse: (sessionId: SessionId, path?: string) => Promise<DiffApprovalBrowseValue>;
|
|
36
36
|
/** Add one named path to the list, then refresh; resolves to what the scan did. */
|
|
37
|
-
addPath: (sessionId: SessionId, path: string, includeUnchanged: boolean) => Promise<DiffApprovalAddValue>;
|
|
37
|
+
addPath: (sessionId: SessionId, path: string, includeUnchanged: boolean, exact?: boolean) => Promise<DiffApprovalAddValue>;
|
|
38
38
|
/** Open one file with its default application or reveal it in the folder. */
|
|
39
39
|
open: (sessionId: SessionId, id: string, action: DiffApprovalOpenAction) => Promise<void>;
|
|
40
40
|
/** Keep every pending entry of one session in a single host call, then refresh. */
|
package/lib/types/types.d.ts
CHANGED
|
@@ -188,6 +188,11 @@ export type DiffApprovalAddOutcome =
|
|
|
188
188
|
| 'empty'
|
|
189
189
|
/** The path does not exist (or is neither a file nor a directory). */
|
|
190
190
|
| 'missing'
|
|
191
|
+
/**
|
|
192
|
+
* The caller named one exact file and the path is a directory. Refused before anything is
|
|
193
|
+
* scanned, so a mistyped path cannot add a whole subtree.
|
|
194
|
+
*/
|
|
195
|
+
| 'not-a-file'
|
|
191
196
|
/** The path lies outside the session's workspace. */
|
|
192
197
|
| 'outside'
|
|
193
198
|
/** The workspace is not inside a git/svn/p4 checkout. */
|
|
@@ -201,6 +206,12 @@ export interface DiffApprovalAddValue {
|
|
|
201
206
|
added: number;
|
|
202
207
|
/** How many scanned paths were already listed (left untouched). */
|
|
203
208
|
duplicates: number;
|
|
209
|
+
/**
|
|
210
|
+
* The entry a single-file add landed as (the one already listed, for a duplicate). Absent
|
|
211
|
+
* for a directory add, which is about many files. It is what lets a caller that named one
|
|
212
|
+
* path select the file without waiting for the next list poll.
|
|
213
|
+
*/
|
|
214
|
+
id?: string | undefined;
|
|
204
215
|
/** Whether the no-change walk hit its file cap, so some files were not added. */
|
|
205
216
|
truncated?: boolean | undefined;
|
|
206
217
|
/** Failure detail for `outcome: 'failed'`. */
|
package/package.json
CHANGED