dsh-diff-approval 0.29.1 → 0.31.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 +7 -4
- package/README.zh.md +7 -4
- package/assets/fonts/README.md +10 -8
- package/assets/fonts/manifest.json +1 -1
- package/lib/client.js +5161 -1972
- package/lib/index.js +4331 -442
- package/lib/types/annotate-skill.d.ts +34 -0
- package/lib/types/annotate-tool.d.ts +227 -0
- package/lib/types/annotate.d.ts +186 -0
- package/lib/types/atomic-write.d.ts +77 -0
- package/lib/types/client/PendingPanel.d.ts +92 -24
- package/lib/types/client/category-color.d.ts +62 -0
- package/lib/types/client/chords.d.ts +70 -17
- package/lib/types/client/discussion.d.ts +76 -16
- package/lib/types/client/dock.d.ts +8 -8
- package/lib/types/client/dsh-icons.d.ts +98 -0
- package/lib/types/client/header-entry.d.ts +27 -11
- package/lib/types/client/ids.d.ts +18 -0
- package/lib/types/client/locales.d.ts +88 -36
- package/lib/types/client/panel-memory.d.ts +118 -35
- package/lib/types/client/path-match.d.ts +50 -0
- package/lib/types/client/port.d.ts +77 -1
- package/lib/types/client/presentation-menu.d.ts +1 -1
- package/lib/types/client/produced-diff.d.ts +136 -22
- package/lib/types/client/reference.d.ts +0 -2
- package/lib/types/client/remap-sync.d.ts +18 -1
- package/lib/types/client/session-seat.d.ts +93 -0
- package/lib/types/client/settings.d.ts +40 -14
- package/lib/types/client/slots.d.ts +184 -12
- package/lib/types/client/store.d.ts +85 -2
- package/lib/types/comment-ask.d.ts +236 -0
- package/lib/types/comment-lines.d.ts +131 -0
- package/lib/types/comments.d.ts +465 -0
- package/lib/types/index.d.ts +7 -2
- package/lib/types/pending.d.ts +53 -4
- package/lib/types/types.d.ts +356 -4
- package/lib/types/vcs.d.ts +53 -26
- package/lib/types/version.d.ts +162 -0
- package/package.json +7 -2
- package/lib/types/client/chat-bridge.d.ts +0 -70
|
@@ -20,14 +20,15 @@
|
|
|
20
20
|
import type { ReactNode } from 'react';
|
|
21
21
|
import type { HostObservable, InjectFace, PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
|
|
22
22
|
import type { SessionId } from '@deepseek-ai/dsh-client-connection/client';
|
|
23
|
-
import type { PendingDiffSnapshot } from './slots.ts';
|
|
23
|
+
import type { PendingDiffSnapshot, PendingViewHooks } from './slots.ts';
|
|
24
24
|
import type { DockSnapshot } from './dock.tsx';
|
|
25
|
-
/** What the header entry reads from this plugin's own face: the two observables
|
|
26
|
-
*
|
|
27
|
-
* events, so the entry never holds a copy of the panel's
|
|
28
|
-
|
|
25
|
+
/** What the header entry reads from this plugin's own face: the two observables, and the per-session
|
|
26
|
+
* view reader (`pendingView`) that keeps its count on ITS session. Everything else it needs (the
|
|
27
|
+
* button's own click) goes through the window events, so the entry never holds a copy of the panel's
|
|
28
|
+
* state. */
|
|
29
|
+
export interface HeaderEntryFace extends PendingViewHooks {
|
|
29
30
|
hooks: {
|
|
30
|
-
/** Live pending-diff snapshot: the count
|
|
31
|
+
/** Live pending-diff snapshot: the fallback count for a face with no per-session reader. */
|
|
31
32
|
pending: HostObservable<PendingDiffSnapshot>;
|
|
32
33
|
/** The dock's state, absent in a build without a right sidebar. */
|
|
33
34
|
dock?: HostObservable<DockSnapshot>;
|
|
@@ -38,15 +39,30 @@ export interface HeaderEntryFace {
|
|
|
38
39
|
export interface HeaderEntrySeat {
|
|
39
40
|
/** The selected session and its rows; the entry is inert without one. */
|
|
40
41
|
useSessions?: ((select: (state: HeaderEntrySessions) => boolean) => boolean) | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* The session this seat is about, composed by the shell.
|
|
44
|
+
*
|
|
45
|
+
* This is where 0.1.7 hands it over: the session-list store it gives `useSessions` carries
|
|
46
|
+
* `{ ids, byId, phase, projectionsBySession }` and no selected session at all, while the shell's
|
|
47
|
+
* own session-scoped seats take the id from their props and ask the store about that row
|
|
48
|
+
* (`useSessions(s => s.byId[sessionId]?.blank)`). Older shells put `current` in the store, which is
|
|
49
|
+
* why both are read (see `session-seat.ts`).
|
|
50
|
+
*/
|
|
51
|
+
sessionId?: SessionId | undefined;
|
|
41
52
|
}
|
|
42
|
-
/** The slice of the session list this entry reads. */
|
|
53
|
+
/** The slice of the session list this entry reads: whichever of these a shell carries. */
|
|
43
54
|
export interface HeaderEntrySessions {
|
|
44
|
-
/** The session the app is showing. */
|
|
55
|
+
/** The session the app is showing, on the shells that keep it here (0.1.5 and earlier). */
|
|
45
56
|
current?: SessionId | undefined;
|
|
46
57
|
/** Known sessions by id, for the blank-session check. */
|
|
47
|
-
byId
|
|
58
|
+
byId?: Record<string, {
|
|
48
59
|
blank?: boolean;
|
|
49
|
-
} | undefined
|
|
60
|
+
} | undefined> | undefined;
|
|
61
|
+
/** A blank flag carried by the STATE itself on the shells that place it there. */
|
|
62
|
+
blank?: boolean | undefined;
|
|
63
|
+
/** Every other field a shell may carry: this plugin reads none of them, and a shape it does not
|
|
64
|
+
* know must not disable the entry (see `session-seat.ts`). */
|
|
65
|
+
[field: string]: unknown;
|
|
50
66
|
}
|
|
51
67
|
/** Full props of the header entry: the injected face's hooks bound as
|
|
52
68
|
* `usePending`/`useDock`, the framework seats, and the locale `t`. */
|
|
@@ -56,4 +72,4 @@ export type DiffApprovalHeaderEntryProps = InjectFace<HeaderEntryFace> & HeaderE
|
|
|
56
72
|
* @param props - the bound hooks, the session seat, and the translator.
|
|
57
73
|
* @returns the icon button, with the pending count while there is one.
|
|
58
74
|
*/
|
|
59
|
-
export declare function DiffApprovalHeaderEntry({ usePending, useSessions, useDock, t }: DiffApprovalHeaderEntryProps): ReactNode;
|
|
75
|
+
export declare function DiffApprovalHeaderEntry({ usePending, useSessions, useDock, pendingView, sessionId, t }: DiffApprovalHeaderEntryProps): ReactNode;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A fresh identifier for a record the browser half mints.
|
|
3
|
+
*
|
|
4
|
+
* `crypto.randomUUID` is a SECURE CONTEXT API. Reaching this host from a phone or a tablet over the
|
|
5
|
+
* LAN means plain HTTP, where `crypto.randomUUID` is undefined and calling it throws a TypeError —
|
|
6
|
+
* synchronously, before the code around it does anything. That is how writing a comment died on a
|
|
7
|
+
* tablet: the composer stayed open with the reader's words in it, nothing was sent, and no failure was
|
|
8
|
+
* shown, because the throw happened before the request and outside the `try` that would have said so.
|
|
9
|
+
* The desktop was never affected: `localhost` IS a secure context.
|
|
10
|
+
*
|
|
11
|
+
* `crypto.getRandomValues` carries no such restriction, so the fallback builds the id from it — a
|
|
12
|
+
* version-4 UUID, the shape the host and the client both treat as opaque but which reads as one
|
|
13
|
+
* everywhere it is printed. `randomUUID` is still preferred when it is there: it is the same thing
|
|
14
|
+
* done by the platform.
|
|
15
|
+
*
|
|
16
|
+
* @returns an identifier, unique for practical purposes.
|
|
17
|
+
*/
|
|
18
|
+
export declare function newId(): string;
|
|
@@ -9,25 +9,35 @@ export declare const zh: {
|
|
|
9
9
|
'panel.dockFailed': string;
|
|
10
10
|
'panel.loading': string;
|
|
11
11
|
'panel.readFailed': string;
|
|
12
|
-
'panel.group.current': string;
|
|
13
12
|
'panel.group.others': string;
|
|
14
13
|
'panel.tabs': string;
|
|
15
14
|
'panel.tab.pending': string;
|
|
16
15
|
'panel.tab.comments': string;
|
|
17
16
|
'panel.commentsEmpty': string;
|
|
18
|
-
'panel.commentOutdated': string;
|
|
19
17
|
'panel.aria': string;
|
|
20
18
|
'panel.stats': string;
|
|
21
19
|
'panel.blockPosition': string;
|
|
22
20
|
'panel.blockAtEnd': string;
|
|
23
21
|
'panel.blockAtStart': string;
|
|
24
22
|
'panel.blockSingle': string;
|
|
25
|
-
'
|
|
23
|
+
'chip.openDefault': string;
|
|
24
|
+
'chip.reviewInPanel': string;
|
|
25
|
+
'chip.copyPath': string;
|
|
26
|
+
'chip.about': string;
|
|
27
|
+
'chip.about.title': string;
|
|
28
|
+
'panel.confirmFileTitle': string;
|
|
29
|
+
'panel.batchConfirmTitle': string;
|
|
30
|
+
'chip.about.body': string;
|
|
31
|
+
'chip.about.ok': string;
|
|
32
|
+
'update.chip': string;
|
|
33
|
+
'update.body': string;
|
|
34
|
+
'update.npm': string;
|
|
35
|
+
'update.github': string;
|
|
36
|
+
'update.dismiss': string;
|
|
37
|
+
'chip.gone': string;
|
|
26
38
|
'panel.fileNotPending': string;
|
|
27
39
|
'panel.selectHint': string;
|
|
28
40
|
'panel.searchPlaceholder': string;
|
|
29
|
-
'panel.missing': string;
|
|
30
|
-
'panel.missingHint': string;
|
|
31
41
|
'panel.externalChanged': string;
|
|
32
42
|
'panel.dismiss': string;
|
|
33
43
|
'panel.pasteOnCopy': string;
|
|
@@ -67,12 +77,16 @@ export declare const zh: {
|
|
|
67
77
|
'action.gotoCancel': string;
|
|
68
78
|
'panel.gotoMissing': string;
|
|
69
79
|
'panel.persistFailed': string;
|
|
80
|
+
'panel.commentPersistFailed': string;
|
|
81
|
+
'panel.undoFailed': string;
|
|
70
82
|
'settings.keybindings': string;
|
|
71
83
|
'settings.keybindingsDesc': string;
|
|
72
84
|
'settings.comment': string;
|
|
73
85
|
'settings.commentDesc': string;
|
|
74
86
|
'settings.diffView': string;
|
|
75
87
|
'settings.diffViewDesc': string;
|
|
88
|
+
'settings.chipMenu': string;
|
|
89
|
+
'settings.chipMenu.help': string;
|
|
76
90
|
'settings.diffPreview': string;
|
|
77
91
|
'panel.keyDesc': string;
|
|
78
92
|
'panel.shortcutNone': string;
|
|
@@ -95,12 +109,29 @@ export declare const zh: {
|
|
|
95
109
|
'panel.key.coverRight': string;
|
|
96
110
|
'panel.key.coverTop': string;
|
|
97
111
|
'settings.tabLabel': string;
|
|
98
|
-
'row.create': string;
|
|
99
112
|
'row.failed': string;
|
|
113
|
+
'panel.unseen': string;
|
|
114
|
+
'panel.commentCategory': string;
|
|
100
115
|
'row.dismiss': string;
|
|
101
116
|
'row.keepListed': string;
|
|
102
117
|
'row.keepRemove': string;
|
|
103
118
|
'row.revertRemove': string;
|
|
119
|
+
'row.deleteRemove': string;
|
|
120
|
+
'panel.batchKeepAsk': string;
|
|
121
|
+
'panel.batchKeepRemoveAsk': string;
|
|
122
|
+
'panel.batchRevertAsk': string;
|
|
123
|
+
'panel.batchRevertRemoveAsk': string;
|
|
124
|
+
'panel.batchKeepAllAsk': string;
|
|
125
|
+
'panel.batchRevertAllAsk': string;
|
|
126
|
+
'panel.batchRevertAllDeletedAsk': string;
|
|
127
|
+
'panel.batchCloseAsk': string;
|
|
128
|
+
'panel.batchDeletes': string;
|
|
129
|
+
'panel.batchDeletesList': string;
|
|
130
|
+
'panel.batchGo': string;
|
|
131
|
+
'panel.removeOneAsk': string;
|
|
132
|
+
'panel.removeCommentsOne': string;
|
|
133
|
+
'panel.removeCommentsMany': string;
|
|
134
|
+
'panel.batchCommentsList': string;
|
|
104
135
|
'row.added': string;
|
|
105
136
|
'row.removed': string;
|
|
106
137
|
'action.keep': string;
|
|
@@ -110,15 +141,17 @@ export declare const zh: {
|
|
|
110
141
|
'action.discussionCollapse': string;
|
|
111
142
|
'discussion.placeholder': string;
|
|
112
143
|
'discussion.marker': string;
|
|
144
|
+
'discussion.frameLegend': string;
|
|
145
|
+
'discussion.deletedLabel': string;
|
|
113
146
|
'discussion.promptRule': string;
|
|
114
147
|
'discussion.promptRuleSkill': string;
|
|
115
148
|
'discussion.thinking': string;
|
|
116
|
-
'discussion.queued': string;
|
|
117
|
-
'discussion.answering': string;
|
|
118
149
|
'discussion.outdatedQuote': string;
|
|
119
150
|
'discussion.hidden': string;
|
|
120
151
|
'discussion.failed': string;
|
|
121
152
|
'discussion.stopped': string;
|
|
153
|
+
'discussion.addMissing': string;
|
|
154
|
+
'discussion.askMissing': string;
|
|
122
155
|
'action.revert': string;
|
|
123
156
|
'action.delete': string;
|
|
124
157
|
'action.discussionEnd': string;
|
|
@@ -138,10 +171,6 @@ export declare const zh: {
|
|
|
138
171
|
'action.viewUnified': string;
|
|
139
172
|
'action.viewPreview': string;
|
|
140
173
|
'action.viewSource': string;
|
|
141
|
-
'action.viewBefore': string;
|
|
142
|
-
'action.viewAfter': string;
|
|
143
|
-
'action.viewSingle': string;
|
|
144
|
-
'action.viewDouble': string;
|
|
145
174
|
'panel.mdPreviewFailed': string;
|
|
146
175
|
'action.copyHint': string;
|
|
147
176
|
'action.copied': string;
|
|
@@ -161,7 +190,6 @@ export declare const zh: {
|
|
|
161
190
|
'panel.importFailed': string;
|
|
162
191
|
'action.search': string;
|
|
163
192
|
'action.settings': string;
|
|
164
|
-
'action.presentation': string;
|
|
165
193
|
'action.presentationCurrent': string;
|
|
166
194
|
'action.cover': string;
|
|
167
195
|
'cover.left': string;
|
|
@@ -186,13 +214,10 @@ export declare const zh: {
|
|
|
186
214
|
'action.summonHint': string;
|
|
187
215
|
'action.retry': string;
|
|
188
216
|
'panel.crashed': string;
|
|
189
|
-
'status.kept': string;
|
|
190
|
-
'status.reverted': string;
|
|
191
|
-
'status.missing': string;
|
|
192
217
|
'panel.resolvedAsk': string;
|
|
193
218
|
'panel.keepInList': string;
|
|
194
|
-
'panel.
|
|
195
|
-
'panel.
|
|
219
|
+
'panel.keepInListQuiet': string;
|
|
220
|
+
'panel.keepInListQuietHint': string;
|
|
196
221
|
'panel.fileKeptAsk': string;
|
|
197
222
|
'panel.fileRevertedAsk': string;
|
|
198
223
|
'panel.confirmFileRemove': string;
|
|
@@ -221,6 +246,7 @@ export declare const zh: {
|
|
|
221
246
|
'panel.addNoEntries': string;
|
|
222
247
|
'panel.addMissing': string;
|
|
223
248
|
'panel.addOutside': string;
|
|
249
|
+
'panel.addOtherSession': string;
|
|
224
250
|
'panel.addNotAFile': string;
|
|
225
251
|
'panel.addFailed': string;
|
|
226
252
|
'action.cancel': string;
|
|
@@ -247,25 +273,35 @@ export declare const en: {
|
|
|
247
273
|
'panel.dockFailed': string;
|
|
248
274
|
'panel.loading': string;
|
|
249
275
|
'panel.readFailed': string;
|
|
250
|
-
'panel.group.current': string;
|
|
251
276
|
'panel.group.others': string;
|
|
252
277
|
'panel.tabs': string;
|
|
253
278
|
'panel.tab.pending': string;
|
|
254
279
|
'panel.tab.comments': string;
|
|
255
280
|
'panel.commentsEmpty': string;
|
|
256
|
-
'panel.commentOutdated': string;
|
|
257
281
|
'panel.aria': string;
|
|
258
282
|
'panel.stats': string;
|
|
259
283
|
'panel.blockPosition': string;
|
|
260
284
|
'panel.blockAtEnd': string;
|
|
261
285
|
'panel.blockAtStart': string;
|
|
262
286
|
'panel.blockSingle': string;
|
|
263
|
-
'
|
|
287
|
+
'chip.openDefault': string;
|
|
288
|
+
'chip.reviewInPanel': string;
|
|
289
|
+
'chip.copyPath': string;
|
|
290
|
+
'chip.about': string;
|
|
291
|
+
'chip.about.title': string;
|
|
292
|
+
'panel.confirmFileTitle': string;
|
|
293
|
+
'panel.batchConfirmTitle': string;
|
|
294
|
+
'chip.about.body': string;
|
|
295
|
+
'chip.about.ok': string;
|
|
296
|
+
'update.chip': string;
|
|
297
|
+
'update.body': string;
|
|
298
|
+
'update.npm': string;
|
|
299
|
+
'update.github': string;
|
|
300
|
+
'update.dismiss': string;
|
|
301
|
+
'chip.gone': string;
|
|
264
302
|
'panel.fileNotPending': string;
|
|
265
303
|
'panel.selectHint': string;
|
|
266
304
|
'panel.searchPlaceholder': string;
|
|
267
|
-
'panel.missing': string;
|
|
268
|
-
'panel.missingHint': string;
|
|
269
305
|
'panel.externalChanged': string;
|
|
270
306
|
'panel.dismiss': string;
|
|
271
307
|
'panel.pasteOnCopy': string;
|
|
@@ -305,12 +341,16 @@ export declare const en: {
|
|
|
305
341
|
'action.gotoCancel': string;
|
|
306
342
|
'panel.gotoMissing': string;
|
|
307
343
|
'panel.persistFailed': string;
|
|
344
|
+
'panel.commentPersistFailed': string;
|
|
345
|
+
'panel.undoFailed': string;
|
|
308
346
|
'settings.keybindings': string;
|
|
309
347
|
'settings.keybindingsDesc': string;
|
|
310
348
|
'settings.comment': string;
|
|
311
349
|
'settings.commentDesc': string;
|
|
312
350
|
'settings.diffView': string;
|
|
313
351
|
'settings.diffViewDesc': string;
|
|
352
|
+
'settings.chipMenu': string;
|
|
353
|
+
'settings.chipMenu.help': string;
|
|
314
354
|
'settings.diffPreview': string;
|
|
315
355
|
'panel.keyDesc': string;
|
|
316
356
|
'panel.shortcutNone': string;
|
|
@@ -333,12 +373,29 @@ export declare const en: {
|
|
|
333
373
|
'panel.key.coverRight': string;
|
|
334
374
|
'panel.key.coverTop': string;
|
|
335
375
|
'settings.tabLabel': string;
|
|
336
|
-
'row.create': string;
|
|
337
376
|
'row.failed': string;
|
|
377
|
+
'panel.unseen': string;
|
|
378
|
+
'panel.commentCategory': string;
|
|
338
379
|
'row.dismiss': string;
|
|
339
380
|
'row.keepListed': string;
|
|
340
381
|
'row.keepRemove': string;
|
|
341
382
|
'row.revertRemove': string;
|
|
383
|
+
'row.deleteRemove': string;
|
|
384
|
+
'panel.batchKeepAsk': string;
|
|
385
|
+
'panel.batchKeepRemoveAsk': string;
|
|
386
|
+
'panel.batchRevertAsk': string;
|
|
387
|
+
'panel.batchRevertRemoveAsk': string;
|
|
388
|
+
'panel.batchKeepAllAsk': string;
|
|
389
|
+
'panel.batchRevertAllAsk': string;
|
|
390
|
+
'panel.batchRevertAllDeletedAsk': string;
|
|
391
|
+
'panel.batchCloseAsk': string;
|
|
392
|
+
'panel.batchDeletes': string;
|
|
393
|
+
'panel.batchDeletesList': string;
|
|
394
|
+
'panel.batchGo': string;
|
|
395
|
+
'panel.removeOneAsk': string;
|
|
396
|
+
'panel.removeCommentsOne': string;
|
|
397
|
+
'panel.removeCommentsMany': string;
|
|
398
|
+
'panel.batchCommentsList': string;
|
|
342
399
|
'row.added': string;
|
|
343
400
|
'row.removed': string;
|
|
344
401
|
'action.keep': string;
|
|
@@ -348,15 +405,17 @@ export declare const en: {
|
|
|
348
405
|
'action.discussionCollapse': string;
|
|
349
406
|
'discussion.placeholder': string;
|
|
350
407
|
'discussion.marker': string;
|
|
408
|
+
'discussion.frameLegend': string;
|
|
409
|
+
'discussion.deletedLabel': string;
|
|
351
410
|
'discussion.promptRule': string;
|
|
352
411
|
'discussion.promptRuleSkill': string;
|
|
353
412
|
'discussion.thinking': string;
|
|
354
|
-
'discussion.queued': string;
|
|
355
|
-
'discussion.answering': string;
|
|
356
413
|
'discussion.outdatedQuote': string;
|
|
357
414
|
'discussion.hidden': string;
|
|
358
415
|
'discussion.failed': string;
|
|
359
416
|
'discussion.stopped': string;
|
|
417
|
+
'discussion.addMissing': string;
|
|
418
|
+
'discussion.askMissing': string;
|
|
360
419
|
'action.revert': string;
|
|
361
420
|
'action.delete': string;
|
|
362
421
|
'action.discussionEnd': string;
|
|
@@ -376,10 +435,6 @@ export declare const en: {
|
|
|
376
435
|
'action.viewUnified': string;
|
|
377
436
|
'action.viewPreview': string;
|
|
378
437
|
'action.viewSource': string;
|
|
379
|
-
'action.viewBefore': string;
|
|
380
|
-
'action.viewAfter': string;
|
|
381
|
-
'action.viewSingle': string;
|
|
382
|
-
'action.viewDouble': string;
|
|
383
438
|
'panel.mdPreviewFailed': string;
|
|
384
439
|
'action.copyHint': string;
|
|
385
440
|
'action.copied': string;
|
|
@@ -399,7 +454,6 @@ export declare const en: {
|
|
|
399
454
|
'panel.importFailed': string;
|
|
400
455
|
'action.search': string;
|
|
401
456
|
'action.settings': string;
|
|
402
|
-
'action.presentation': string;
|
|
403
457
|
'action.presentationCurrent': string;
|
|
404
458
|
'action.cover': string;
|
|
405
459
|
'cover.left': string;
|
|
@@ -424,13 +478,10 @@ export declare const en: {
|
|
|
424
478
|
'action.summonHint': string;
|
|
425
479
|
'action.retry': string;
|
|
426
480
|
'panel.crashed': string;
|
|
427
|
-
'status.kept': string;
|
|
428
|
-
'status.reverted': string;
|
|
429
|
-
'status.missing': string;
|
|
430
481
|
'panel.resolvedAsk': string;
|
|
431
482
|
'panel.keepInList': string;
|
|
432
|
-
'panel.
|
|
433
|
-
'panel.
|
|
483
|
+
'panel.keepInListQuiet': string;
|
|
484
|
+
'panel.keepInListQuietHint': string;
|
|
434
485
|
'panel.fileKeptAsk': string;
|
|
435
486
|
'panel.fileRevertedAsk': string;
|
|
436
487
|
'panel.confirmFileRemove': string;
|
|
@@ -459,6 +510,7 @@ export declare const en: {
|
|
|
459
510
|
'panel.addNoEntries': string;
|
|
460
511
|
'panel.addMissing': string;
|
|
461
512
|
'panel.addOutside': string;
|
|
513
|
+
'panel.addOtherSession': string;
|
|
462
514
|
'panel.addNotAFile': string;
|
|
463
515
|
'panel.addFailed': string;
|
|
464
516
|
'action.cancel': string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Where the review panel was left,
|
|
2
|
+
* Where the review panel was left, and what the reader has typed but not sent, for
|
|
3
|
+
* this page's lifetime.
|
|
3
4
|
*
|
|
4
5
|
* Closing the panel is not "done reviewing": reopening it should put the reader
|
|
5
6
|
* back on the file they were in, at the offset they were at. That is a fact about
|
|
@@ -13,65 +14,147 @@
|
|
|
13
14
|
*
|
|
14
15
|
* @module dsh-diff-approval/client/panel-memory
|
|
15
16
|
*/
|
|
16
|
-
import type { Discussion } from './discussion.ts';
|
|
17
|
+
import type { Discussion, DiscussionQuoteLine } from './discussion.ts';
|
|
17
18
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
19
|
+
* What the panel keeps about one thread that is NOT the host's to keep: what the reader is
|
|
20
|
+
* typing, whether the block is folded, and the body height the panel last measured for it.
|
|
21
|
+
*
|
|
22
|
+
* A thread itself is the host's record now (see `pending.comments`), so nothing here may
|
|
23
|
+
* hold a turn: the panel renders the snapshot, and this only remembers the page-local
|
|
24
|
+
* presentation of it. That split is what makes a poll harmless — a poll replaces the
|
|
25
|
+
* snapshot, and a draft typed a moment ago is not in it, so keeping the draft here is what
|
|
26
|
+
* stops the poll from clearing the field under the reader's hands.
|
|
22
27
|
*/
|
|
23
|
-
export
|
|
28
|
+
export interface ThreadLocal {
|
|
29
|
+
/** What the reader has typed into the compose row (not sent yet). */
|
|
30
|
+
draft: string;
|
|
31
|
+
/** Folded to the one-row header. */
|
|
32
|
+
collapsed: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* The last send of this thread was refused (no live agent, or the ask itself failed). It is a
|
|
35
|
+
* page-local fact because nothing was stored: the host has no question to record, so the block
|
|
36
|
+
* could only say so from here. Cleared by the next send.
|
|
37
|
+
*/
|
|
38
|
+
failed?: boolean | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* How many rows the block's body was last measured to occupy, or absent before the first
|
|
41
|
+
* measurement. The reservation follows the drawing rather than the other way round (see
|
|
42
|
+
* the panel's read-back), and it is kept here so a mount that comes back draws the thread
|
|
43
|
+
* at the size it was already measured at instead of reserving the model's estimate again.
|
|
44
|
+
*/
|
|
45
|
+
bodyRows?: number | undefined;
|
|
46
|
+
}
|
|
24
47
|
/**
|
|
25
|
-
* The
|
|
48
|
+
* The page-local thread state a session's panel is holding.
|
|
26
49
|
* @param sessionId - the session, if any.
|
|
27
|
-
* @returns the
|
|
50
|
+
* @returns the state by comment id; empty when there is none.
|
|
28
51
|
*/
|
|
29
|
-
export declare function
|
|
52
|
+
export declare function rememberedThreads(sessionId: string | undefined): Readonly<Record<string, ThreadLocal>>;
|
|
30
53
|
/**
|
|
31
|
-
* Remember
|
|
32
|
-
*
|
|
54
|
+
* Remember one session's page-local thread state. Called on every change, so a mount that
|
|
55
|
+
* appears later starts from it.
|
|
33
56
|
* @param sessionId - the session the panel is reviewing; nothing is recorded without one.
|
|
34
|
-
* @param
|
|
57
|
+
* @param threads - the state by comment id.
|
|
35
58
|
*/
|
|
36
|
-
export declare function
|
|
59
|
+
export declare function rememberThreads(sessionId: string | undefined, threads: Readonly<Record<string, ThreadLocal>>): void;
|
|
37
60
|
/**
|
|
38
|
-
*
|
|
61
|
+
* A block the reader has PLACED on a file's lines but has not written down yet.
|
|
39
62
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
63
|
+
* It has no host record (see `sendDiscussion`), so nothing else on this page holds it: without this
|
|
64
|
+
* the reader's complaint was right — placing a comment, typing a first thought and closing the panel
|
|
65
|
+
* threw the whole block away, because only the words were remembered and a comment id to hang them
|
|
66
|
+
* under does not exist until the block is sent. Everything a mount needs to draw the block again is
|
|
67
|
+
* here: the entry it was placed on, the lines, the quote it was placed against, and the words.
|
|
68
|
+
*/
|
|
69
|
+
export interface PlacedThread {
|
|
70
|
+
/**
|
|
71
|
+
* The block's page-local id, minted when it was placed. The comment's own id is minted when the
|
|
72
|
+
* block is written (see `sendDiscussion`), and this is only ever the name of an unsent block.
|
|
73
|
+
*/
|
|
74
|
+
id: string;
|
|
75
|
+
/** The pending entry whose rows it was placed on. */
|
|
76
|
+
fileId: string;
|
|
77
|
+
/**
|
|
78
|
+
* The rows it was made on, plus the new-file lines that survive a rebuild. The lines are what a
|
|
79
|
+
* mount re-anchors from (see `remapDiscussions`); the row indices are the placement's own hint,
|
|
80
|
+
* stale the moment the model moves.
|
|
81
|
+
*/
|
|
82
|
+
anchor: Discussion['anchor'];
|
|
83
|
+
/** The anchored lines as they read when it was placed (the re-anchor fingerprint). */
|
|
84
|
+
quote: string;
|
|
85
|
+
/** `quote` with one line of context on each side, as it read then. */
|
|
86
|
+
quoteContext?: string | undefined;
|
|
87
|
+
/** The gutter numbers of `quote`'s lines, in the same order. */
|
|
88
|
+
quoteLines?: readonly DiscussionQuoteLine[] | undefined;
|
|
89
|
+
/** What the reader had typed into it. */
|
|
90
|
+
draft: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The placed-but-unsent blocks a session's panel is holding.
|
|
94
|
+
* @param sessionId - the session, if any.
|
|
95
|
+
* @returns the blocks, oldest placement first; empty when there are none.
|
|
96
|
+
*/
|
|
97
|
+
export declare function rememberedPlacedThreads(sessionId: string | undefined): readonly PlacedThread[];
|
|
98
|
+
/**
|
|
99
|
+
* Remember one session's placed-but-unsent blocks. Called on every change, so a mount that comes
|
|
100
|
+
* back draws them again on the same lines with the same words.
|
|
44
101
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
102
|
+
* A list that says the same thing as the one held is not stored: the caller rebuilds it per render,
|
|
103
|
+
* and only a real change (a placement, a draft, a block written or discarded) may republish it.
|
|
104
|
+
*
|
|
105
|
+
* @param sessionId - the session the panel is reviewing; nothing is recorded without one.
|
|
106
|
+
* @param threads - the placements, oldest first.
|
|
48
107
|
*/
|
|
49
|
-
export declare function
|
|
108
|
+
export declare function rememberPlacedThreads(sessionId: string | undefined, threads: readonly PlacedThread[]): void;
|
|
50
109
|
/**
|
|
51
|
-
* Drop every
|
|
110
|
+
* Drop every placed block whose file the list no longer holds.
|
|
52
111
|
*
|
|
53
|
-
* A
|
|
54
|
-
* list leaves nothing for its
|
|
55
|
-
*
|
|
56
|
-
*
|
|
112
|
+
* A placement is a block of rows in ONE file's diff, so a file the reader has kept or
|
|
113
|
+
* reverted out of the list leaves nothing for its block to hang on: it goes with the file,
|
|
114
|
+
* exactly as the comments on those rows do (the host drops those; see `comments.ts`). The
|
|
115
|
+
* entry ids ARE paths, so a path that comes back later is the same id again — without this
|
|
116
|
+
* the placement was resurrected onto a file the reader had already dealt with, and
|
|
117
|
+
* `discussionOverlapping` went on refusing a fresh comment on those very rows because a
|
|
118
|
+
* block that is not on screen still counted as theirs.
|
|
119
|
+
*
|
|
120
|
+
* Nothing is published when nothing is dropped, so a poll that changes no file is not a
|
|
121
|
+
* change to the page's memory (see the identity discipline in `rememberPlacedThreads`).
|
|
57
122
|
*
|
|
58
123
|
* @param sessionId - the session the panel is reviewing; nothing is dropped without one.
|
|
59
124
|
* @param listed - the pending entry ids the list is holding.
|
|
60
125
|
*/
|
|
61
|
-
export declare function
|
|
126
|
+
export declare function forgetPlacedThreadsNotIn(sessionId: string | undefined, listed: readonly string[]): void;
|
|
62
127
|
/**
|
|
63
|
-
* Whether the reader asked not to be asked again about
|
|
128
|
+
* Whether the reader asked not to be asked again about rows leaving THIS session's list.
|
|
64
129
|
* @param sessionId - the session the panel is reviewing; nothing is quiet without one.
|
|
65
|
-
* @param fileId - the pending entry the question was about.
|
|
66
130
|
* @returns true when the action should run without the question.
|
|
67
131
|
*/
|
|
68
|
-
export declare function removalAskQuiet(sessionId: string | undefined
|
|
132
|
+
export declare function removalAskQuiet(sessionId: string | undefined): boolean;
|
|
69
133
|
/**
|
|
70
|
-
* Stop asking whether
|
|
134
|
+
* Stop asking whether rows should leave the list, for the rest of this page: the whole session, every
|
|
135
|
+
* file in it.
|
|
71
136
|
* @param sessionId - the session the panel is reviewing; nothing is recorded without one.
|
|
72
|
-
* @param fileId - the pending entry the question was about.
|
|
73
137
|
*/
|
|
74
|
-
export declare function quietenRemovalAsk(sessionId: string | undefined
|
|
138
|
+
export declare function quietenRemovalAsk(sessionId: string | undefined): void;
|
|
139
|
+
/**
|
|
140
|
+
* Window event a dismissal dispatches, so every mounted seat hears it.
|
|
141
|
+
*
|
|
142
|
+
* The notice's chip lives in the open file's status bar, and the panel that draws it can be mounted more than
|
|
143
|
+
* once (the footer seat and the right sidebar's docked tab are separate mounts): the state above is the fact,
|
|
144
|
+
* and this event is how the OTHER mount learns about it NOW rather than at its next mount. One state, one
|
|
145
|
+
* event — so whichever seat is on screen cannot disagree about whether the reader has said "got it".
|
|
146
|
+
*/
|
|
147
|
+
export declare const UPDATE_DISMISSED_EVENT = "diff-approval:update-dismissed";
|
|
148
|
+
/**
|
|
149
|
+
* The release whose notice the reader dismissed on this page.
|
|
150
|
+
* @returns the dismissed version, or `''` when none has been dismissed here.
|
|
151
|
+
*/
|
|
152
|
+
export declare function dismissedUpdateVersion(): string;
|
|
153
|
+
/**
|
|
154
|
+
* Remember that the reader dismissed the notice for one version on this page, and tell the other mounts.
|
|
155
|
+
* @param version - the version that notice was about.
|
|
156
|
+
*/
|
|
157
|
+
export declare function dismissUpdate(version: string): void;
|
|
75
158
|
/**
|
|
76
159
|
* Remember that a session's panel was left showing one file, and where in it.
|
|
77
160
|
* @param sessionId - the session the panel was reviewing; nothing is recorded
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path comparison for the review's own references: is the path a press named the same file as one the
|
|
3
|
+
* pending list holds?
|
|
4
|
+
*
|
|
5
|
+
* Its own module because three places ask it and they must not disagree — the panel's jump to a file, the
|
|
6
|
+
* plugin's produced-file press bridge, and the store's "does the page hold this path" reader — while the
|
|
7
|
+
* panel itself is a React component module that a data-layer reader should not have to import.
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-diff-approval/client/path-match
|
|
10
|
+
*/
|
|
11
|
+
/** Normalize a path for comparison: forward slashes, no trailing slash. */
|
|
12
|
+
export declare function normalizeDiffPath(p: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* The directory a file path lives in, as the path was spelled.
|
|
15
|
+
*
|
|
16
|
+
* @param p - the file's own path.
|
|
17
|
+
* @returns the directory, or undefined when the path names no directory (empty, or a bare file name).
|
|
18
|
+
*/
|
|
19
|
+
export declare function directoryOfPath(p: string | undefined): string | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* The absolute path a Markdown link names, resolved the way Markdown means it: against the directory of
|
|
22
|
+
* the file the preview is showing.
|
|
23
|
+
*
|
|
24
|
+
* A link in a document is relative to THAT DOCUMENT — `../src/foo.ts` in `docs/a.md` is `src/foo.ts` at the
|
|
25
|
+
* workspace root, not `../src/foo.ts` of the page's own URL — which is why the base is the previewed file's
|
|
26
|
+
* own directory and not the workspace root. The href is percent-decoded, its `#line`/`?query` suffix is
|
|
27
|
+
* dropped, `.`/`..` are resolved, and both separators are accepted. An href that is already absolute
|
|
28
|
+
* (drive letter or a leading slash) needs no base.
|
|
29
|
+
*
|
|
30
|
+
* Exported so the panel's preview click and its tests share one implementation and cannot disagree about
|
|
31
|
+
* what a link points at.
|
|
32
|
+
*
|
|
33
|
+
* @param baseDirectory - the directory of the file being previewed, or the workspace root when that file's
|
|
34
|
+
* own path is unknown.
|
|
35
|
+
* @param href - the anchor's href, as written in the Markdown.
|
|
36
|
+
* @returns the absolute path, or undefined when it cannot be named (an empty href, or a relative href with
|
|
37
|
+
* no base to resolve against).
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveMarkdownHref(baseDirectory: string | undefined, href: string): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Whether a produced-file chip path and a pending file path refer to the same file, tolerant of separator
|
|
42
|
+
* style (\\ vs /) and of a workspace-relative vs absolute form. `chipPath` is typically the harness's
|
|
43
|
+
* workspace-relative forward-slash path; `filePath` is the host's absolute native-separator path. Matching
|
|
44
|
+
* is case-insensitive so a Windows drive/segment case difference does not miss the file the user clicked.
|
|
45
|
+
* @param chipPath - the path a press (or a reference) named.
|
|
46
|
+
* @param filePath - the path the pending list holds.
|
|
47
|
+
* @param workspacePath - the session's workspace root, when it is known.
|
|
48
|
+
* @returns whether the two name one file.
|
|
49
|
+
*/
|
|
50
|
+
export declare function diffPathsMatch(chipPath: string, filePath: string, workspacePath: string | undefined): boolean;
|