xtralab 0.15.1 → 0.15.2
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 +58 -33
- package/lib/fileBrowser/commands.d.ts +1 -0
- package/lib/fileBrowser/commands.js +46 -1
- package/lib/fileBrowser/fileBrowser.js +4 -8
- package/lib/fileBrowser/gitStatus.d.ts +16 -5
- package/lib/fileBrowser/gitStatus.js +28 -17
- package/lib/fileBrowser/widget.d.ts +15 -0
- package/lib/fileBrowser/widget.js +13 -0
- package/lib/git/commands.d.ts +5 -0
- package/lib/git/commands.js +4 -3
- package/lib/git/diffPreferences.d.ts +90 -0
- package/lib/git/diffPreferences.js +107 -0
- package/lib/git/diffProvider.js +10 -2
- package/lib/git/diffSurface.d.ts +34 -19
- package/lib/git/diffSurface.js +49 -115
- package/lib/git/diffTheme.d.ts +7 -0
- package/lib/git/diffTheme.js +23 -0
- package/lib/git/diffWidget.d.ts +7 -30
- package/lib/git/diffWidget.js +56 -100
- package/lib/git/imageDiff.d.ts +9 -0
- package/lib/git/imageDiff.js +2 -28
- package/lib/git/index.js +41 -2
- package/lib/git/notebookDiff.js +3 -2
- package/package.json +5 -3
- package/schema/git-diff-preferences.json +42 -0
- package/src/fileBrowser/commands.ts +64 -0
- package/src/fileBrowser/fileBrowser.tsx +4 -9
- package/src/fileBrowser/gitStatus.ts +33 -20
- package/src/fileBrowser/widget.tsx +22 -0
- package/src/git/commands.ts +13 -1
- package/src/git/diffPreferences.ts +192 -0
- package/src/git/diffProvider.tsx +11 -2
- package/src/git/diffSurface.tsx +113 -146
- package/src/git/diffTheme.ts +24 -0
- package/src/git/diffWidget.tsx +108 -138
- package/src/git/imageDiff.tsx +12 -34
- package/src/git/index.ts +51 -2
- package/src/git/notebookDiff.tsx +3 -2
- package/style/git.css +4 -2
package/src/git/diffWidget.tsx
CHANGED
|
@@ -15,19 +15,19 @@ import type { SelectedLineRange } from '@pierre/diffs';
|
|
|
15
15
|
import type { IAskAgent } from '../askAgent/tokens';
|
|
16
16
|
|
|
17
17
|
import { buildDiffAskRequest } from './askRequest';
|
|
18
|
+
import {
|
|
19
|
+
useDiffPreferences,
|
|
20
|
+
type IDiffPreferences,
|
|
21
|
+
type ImageDiffViewMode
|
|
22
|
+
} from './diffPreferences';
|
|
18
23
|
import {
|
|
19
24
|
DIFF_WIDGET_CSS_CLASS,
|
|
20
25
|
DiffStyleControl,
|
|
21
26
|
DiffSurface,
|
|
27
|
+
LineWrapControl,
|
|
22
28
|
NotebookViewModeControl,
|
|
23
29
|
isDarkTheme,
|
|
24
|
-
isPierreTheme
|
|
25
|
-
readStoredDiffStyle,
|
|
26
|
-
readStoredNotebookViewMode,
|
|
27
|
-
writeStoredDiffStyle,
|
|
28
|
-
writeStoredNotebookViewMode,
|
|
29
|
-
type DiffStyle,
|
|
30
|
-
type NotebookDiffViewMode
|
|
30
|
+
isPierreTheme
|
|
31
31
|
} from './diffSurface';
|
|
32
32
|
import { imageDataType } from './imageDiff';
|
|
33
33
|
|
|
@@ -73,6 +73,10 @@ export interface IXtralabDiffContext {
|
|
|
73
73
|
* When available, diff line selections get an "ask an agent" gutter button.
|
|
74
74
|
*/
|
|
75
75
|
askAgent: IAskAgent | null;
|
|
76
|
+
/**
|
|
77
|
+
* The display choices shared by all diff views.
|
|
78
|
+
*/
|
|
79
|
+
preferences: IDiffPreferences;
|
|
76
80
|
/**
|
|
77
81
|
* The application translation bundle.
|
|
78
82
|
*/
|
|
@@ -90,8 +94,6 @@ export class XtralabDiffWidget
|
|
|
90
94
|
super();
|
|
91
95
|
this._model = model;
|
|
92
96
|
this._context = context;
|
|
93
|
-
this._notebookViewMode = readStoredNotebookViewMode();
|
|
94
|
-
this._diffStyle = readStoredDiffStyle();
|
|
95
97
|
// Reuse jupyterlab-git's host sizing while applying xtralab styling.
|
|
96
98
|
this.addClass('jp-git-diff-root');
|
|
97
99
|
this.addClass(DIFF_WIDGET_CSS_CLASS);
|
|
@@ -149,32 +151,6 @@ export class XtralabDiffWidget
|
|
|
149
151
|
await done.promise;
|
|
150
152
|
}
|
|
151
153
|
|
|
152
|
-
/**
|
|
153
|
-
* The current rendered-vs-JSON choice for notebook diffs.
|
|
154
|
-
*/
|
|
155
|
-
get notebookViewMode(): NotebookDiffViewMode {
|
|
156
|
-
return this._notebookViewMode;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Set the notebook view mode and persist it.
|
|
161
|
-
*/
|
|
162
|
-
setNotebookViewMode(mode: NotebookDiffViewMode): void {
|
|
163
|
-
if (mode === this._notebookViewMode) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
this._notebookViewMode = mode;
|
|
167
|
-
writeStoredNotebookViewMode(mode);
|
|
168
|
-
this._notebookViewModeChanged.emit(mode);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* A signal emitted when the notebook view mode changes.
|
|
173
|
-
*/
|
|
174
|
-
get notebookViewModeChanged(): ISignal<this, NotebookDiffViewMode> {
|
|
175
|
-
return this._notebookViewModeChanged;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
154
|
/**
|
|
179
155
|
* Whether a rendered notebook view is currently available.
|
|
180
156
|
*/
|
|
@@ -201,33 +177,7 @@ export class XtralabDiffWidget
|
|
|
201
177
|
}
|
|
202
178
|
|
|
203
179
|
/**
|
|
204
|
-
*
|
|
205
|
-
*/
|
|
206
|
-
get diffStyle(): DiffStyle {
|
|
207
|
-
return this._diffStyle;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Set the diff style and persist it.
|
|
212
|
-
*/
|
|
213
|
-
setDiffStyle(style: DiffStyle): void {
|
|
214
|
-
if (style === this._diffStyle) {
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
this._diffStyle = style;
|
|
218
|
-
writeStoredDiffStyle(style);
|
|
219
|
-
this._diffStyleChanged.emit(style);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* A signal emitted when the diff style changes.
|
|
224
|
-
*/
|
|
225
|
-
get diffStyleChanged(): ISignal<this, DiffStyle> {
|
|
226
|
-
return this._diffStyleChanged;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Whether the Split/Unified toolbar selector currently applies.
|
|
180
|
+
* Whether the Split/Unified and line-wrap toolbar controls currently apply.
|
|
231
181
|
*/
|
|
232
182
|
get fileDiffActive(): boolean {
|
|
233
183
|
return this._fileDiffActive;
|
|
@@ -309,14 +259,8 @@ export class XtralabDiffWidget
|
|
|
309
259
|
private _context: IXtralabDiffContext;
|
|
310
260
|
private _reloadNonce = 0;
|
|
311
261
|
private _pendingRefresh: PromiseDelegate<void> | null = null;
|
|
312
|
-
private _notebookViewMode: NotebookDiffViewMode;
|
|
313
|
-
private _notebookViewModeChanged = new Signal<this, NotebookDiffViewMode>(
|
|
314
|
-
this
|
|
315
|
-
);
|
|
316
262
|
private _hasNotebookView = false;
|
|
317
263
|
private _hasNotebookViewChanged = new Signal<this, boolean>(this);
|
|
318
|
-
private _diffStyle: DiffStyle;
|
|
319
|
-
private _diffStyleChanged = new Signal<this, DiffStyle>(this);
|
|
320
264
|
private _fileDiffActive = false;
|
|
321
265
|
private _fileDiffActiveChanged = new Signal<this, boolean>(this);
|
|
322
266
|
private _emptied = new Signal<this, void>(this);
|
|
@@ -349,8 +293,15 @@ function ModelDiffView(props: {
|
|
|
349
293
|
}): React.ReactElement {
|
|
350
294
|
const { widget } = props;
|
|
351
295
|
const model = widget.model as IXtralabDiffModel;
|
|
352
|
-
const {
|
|
353
|
-
|
|
296
|
+
const {
|
|
297
|
+
contentsManager,
|
|
298
|
+
rendermime,
|
|
299
|
+
themeManager,
|
|
300
|
+
askAgent,
|
|
301
|
+
preferences,
|
|
302
|
+
trans
|
|
303
|
+
} = widget.context;
|
|
304
|
+
const values = useDiffPreferences(preferences);
|
|
354
305
|
const nonce = widget.reloadNonce;
|
|
355
306
|
|
|
356
307
|
const [state, setState] = React.useState<IModelDiffState>({
|
|
@@ -360,22 +311,6 @@ function ModelDiffView(props: {
|
|
|
360
311
|
error: null
|
|
361
312
|
});
|
|
362
313
|
|
|
363
|
-
const [notebookViewMode, setNotebookViewMode] =
|
|
364
|
-
React.useState<NotebookDiffViewMode>(() => widget.notebookViewMode);
|
|
365
|
-
React.useEffect(() => {
|
|
366
|
-
const handler = (
|
|
367
|
-
sender: XtralabDiffWidget,
|
|
368
|
-
mode: NotebookDiffViewMode
|
|
369
|
-
): void => {
|
|
370
|
-
setNotebookViewMode(mode);
|
|
371
|
-
};
|
|
372
|
-
widget.notebookViewModeChanged.connect(handler);
|
|
373
|
-
setNotebookViewMode(widget.notebookViewMode);
|
|
374
|
-
return () => {
|
|
375
|
-
widget.notebookViewModeChanged.disconnect(handler);
|
|
376
|
-
};
|
|
377
|
-
}, [widget]);
|
|
378
|
-
|
|
379
314
|
const handleNotebookAvailabilityChange = React.useCallback(
|
|
380
315
|
(available: boolean) => {
|
|
381
316
|
widget.setHasNotebookView(available);
|
|
@@ -383,19 +318,19 @@ function ModelDiffView(props: {
|
|
|
383
318
|
[widget]
|
|
384
319
|
);
|
|
385
320
|
|
|
386
|
-
const
|
|
387
|
-
() =>
|
|
321
|
+
const handleSplitRatioChange = React.useCallback(
|
|
322
|
+
(splitRatio: number) => {
|
|
323
|
+
preferences.update({ splitRatio });
|
|
324
|
+
},
|
|
325
|
+
[preferences]
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
const handleImageViewModeChange = React.useCallback(
|
|
329
|
+
(imageViewMode: ImageDiffViewMode) => {
|
|
330
|
+
preferences.update({ imageViewMode });
|
|
331
|
+
},
|
|
332
|
+
[preferences]
|
|
388
333
|
);
|
|
389
|
-
React.useEffect(() => {
|
|
390
|
-
const handler = (sender: XtralabDiffWidget, style: DiffStyle): void => {
|
|
391
|
-
setDiffStyle(style);
|
|
392
|
-
};
|
|
393
|
-
widget.diffStyleChanged.connect(handler);
|
|
394
|
-
setDiffStyle(widget.diffStyle);
|
|
395
|
-
return () => {
|
|
396
|
-
widget.diffStyleChanged.disconnect(handler);
|
|
397
|
-
};
|
|
398
|
-
}, [widget]);
|
|
399
334
|
|
|
400
335
|
const handleFileDiffActiveChange = React.useCallback(
|
|
401
336
|
(active: boolean) => {
|
|
@@ -562,8 +497,13 @@ function ModelDiffView(props: {
|
|
|
562
497
|
dark={dark}
|
|
563
498
|
pierreTheme={pierre}
|
|
564
499
|
rendermime={rendermime}
|
|
565
|
-
notebookViewMode={notebookViewMode}
|
|
566
|
-
diffStyle={diffStyle}
|
|
500
|
+
notebookViewMode={values.notebookViewMode}
|
|
501
|
+
diffStyle={values.diffStyle}
|
|
502
|
+
lineWrap={values.lineWrap}
|
|
503
|
+
splitRatio={values.splitRatio}
|
|
504
|
+
onSplitRatioChange={handleSplitRatioChange}
|
|
505
|
+
imageViewMode={values.imageViewMode}
|
|
506
|
+
onImageViewModeChange={handleImageViewModeChange}
|
|
567
507
|
onNotebookAvailabilityChange={handleNotebookAvailabilityChange}
|
|
568
508
|
onFileDiffActiveChange={handleFileDiffActiveChange}
|
|
569
509
|
onMetadataChange={handleMetadataChange}
|
|
@@ -598,38 +538,27 @@ function NotebookViewModeToolbarControl(props: {
|
|
|
598
538
|
widget: XtralabDiffWidget;
|
|
599
539
|
}): React.ReactElement {
|
|
600
540
|
const { widget } = props;
|
|
601
|
-
const
|
|
602
|
-
|
|
603
|
-
);
|
|
541
|
+
const { preferences, trans } = widget.context;
|
|
542
|
+
const { notebookViewMode } = useDiffPreferences(preferences);
|
|
604
543
|
const [available, setAvailable] = React.useState<boolean>(
|
|
605
544
|
() => widget.hasNotebookView
|
|
606
545
|
);
|
|
607
546
|
React.useEffect(() => {
|
|
608
|
-
const onMode = (
|
|
609
|
-
sender: XtralabDiffWidget,
|
|
610
|
-
next: NotebookDiffViewMode
|
|
611
|
-
): void => {
|
|
612
|
-
setMode(next);
|
|
613
|
-
};
|
|
614
547
|
const onAvailable = (sender: XtralabDiffWidget, next: boolean): void => {
|
|
615
548
|
setAvailable(next);
|
|
616
549
|
};
|
|
617
|
-
widget.notebookViewModeChanged.connect(onMode);
|
|
618
550
|
widget.hasNotebookViewChanged.connect(onAvailable);
|
|
619
|
-
setMode(widget.notebookViewMode);
|
|
620
551
|
setAvailable(widget.hasNotebookView);
|
|
621
552
|
return () => {
|
|
622
|
-
widget.notebookViewModeChanged.disconnect(onMode);
|
|
623
553
|
widget.hasNotebookViewChanged.disconnect(onAvailable);
|
|
624
554
|
};
|
|
625
555
|
}, [widget]);
|
|
626
556
|
|
|
627
|
-
const trans = widget.context.trans;
|
|
628
557
|
return (
|
|
629
558
|
<NotebookViewModeControl
|
|
630
|
-
mode={
|
|
559
|
+
mode={notebookViewMode}
|
|
631
560
|
available={available}
|
|
632
|
-
onChange={next =>
|
|
561
|
+
onChange={next => preferences.update({ notebookViewMode: next })}
|
|
633
562
|
trans={trans}
|
|
634
563
|
/>
|
|
635
564
|
);
|
|
@@ -659,38 +588,78 @@ function DiffStyleToolbarControl(props: {
|
|
|
659
588
|
widget: XtralabDiffWidget;
|
|
660
589
|
}): React.ReactElement {
|
|
661
590
|
const { widget } = props;
|
|
662
|
-
const
|
|
663
|
-
const
|
|
664
|
-
|
|
591
|
+
const { preferences, trans } = widget.context;
|
|
592
|
+
const { diffStyle, diffStyleControl } = useDiffPreferences(preferences);
|
|
593
|
+
const available = useFileDiffActive(widget);
|
|
594
|
+
return (
|
|
595
|
+
<DiffStyleControl
|
|
596
|
+
diffStyle={diffStyle}
|
|
597
|
+
control={diffStyleControl}
|
|
598
|
+
available={available}
|
|
599
|
+
onChange={next => preferences.update({ diffStyle: next })}
|
|
600
|
+
trans={trans}
|
|
601
|
+
/>
|
|
665
602
|
);
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
widget
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Line-wrap toggle mounted into a host-owned toolbar.
|
|
607
|
+
*/
|
|
608
|
+
class LineWrapToolbarItem extends ReactWidget {
|
|
609
|
+
constructor(widget: XtralabDiffWidget) {
|
|
610
|
+
super();
|
|
611
|
+
this._widget = widget;
|
|
612
|
+
this.addClass('jp-xtralab-DiffWidget-lineWrapToolbarItem');
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Render the line-wrap toggle.
|
|
617
|
+
*/
|
|
618
|
+
protected render(): React.ReactElement {
|
|
619
|
+
return <LineWrapToolbarControl widget={this._widget} />;
|
|
620
|
+
}
|
|
682
621
|
|
|
683
|
-
|
|
622
|
+
private _widget: XtralabDiffWidget;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
function LineWrapToolbarControl(props: {
|
|
626
|
+
widget: XtralabDiffWidget;
|
|
627
|
+
}): React.ReactElement {
|
|
628
|
+
const { widget } = props;
|
|
629
|
+
const { preferences, trans } = widget.context;
|
|
630
|
+
const { lineWrap } = useDiffPreferences(preferences);
|
|
631
|
+
const available = useFileDiffActive(widget);
|
|
684
632
|
return (
|
|
685
|
-
<
|
|
686
|
-
|
|
633
|
+
<LineWrapControl
|
|
634
|
+
lineWrap={lineWrap}
|
|
687
635
|
available={available}
|
|
688
|
-
onChange={next =>
|
|
636
|
+
onChange={next => preferences.update({ lineWrap: next })}
|
|
689
637
|
trans={trans}
|
|
690
638
|
/>
|
|
691
639
|
);
|
|
692
640
|
}
|
|
693
641
|
|
|
642
|
+
/**
|
|
643
|
+
* Track {@link XtralabDiffWidget.fileDiffActive} for the split/unified and
|
|
644
|
+
* line-wrap controls.
|
|
645
|
+
*/
|
|
646
|
+
function useFileDiffActive(widget: XtralabDiffWidget): boolean {
|
|
647
|
+
const [active, setActive] = React.useState<boolean>(
|
|
648
|
+
() => widget.fileDiffActive
|
|
649
|
+
);
|
|
650
|
+
React.useEffect(() => {
|
|
651
|
+
const onActive = (sender: XtralabDiffWidget, next: boolean): void => {
|
|
652
|
+
setActive(next);
|
|
653
|
+
};
|
|
654
|
+
widget.fileDiffActiveChanged.connect(onActive);
|
|
655
|
+
setActive(widget.fileDiffActive);
|
|
656
|
+
return () => {
|
|
657
|
+
widget.fileDiffActiveChanged.disconnect(onActive);
|
|
658
|
+
};
|
|
659
|
+
}, [widget]);
|
|
660
|
+
return active;
|
|
661
|
+
}
|
|
662
|
+
|
|
694
663
|
/**
|
|
695
664
|
* Structural toolbar type shared across host package boundaries.
|
|
696
665
|
*/
|
|
@@ -713,4 +682,5 @@ export function addDiffToolbarItems(
|
|
|
713
682
|
new NotebookViewModeToolbarItem(widget)
|
|
714
683
|
);
|
|
715
684
|
toolbar.addItem('xtralab-diff-style', new DiffStyleToolbarItem(widget));
|
|
685
|
+
toolbar.addItem('xtralab-diff-line-wrap', new LineWrapToolbarItem(widget));
|
|
716
686
|
}
|
package/src/git/imageDiff.tsx
CHANGED
|
@@ -2,6 +2,8 @@ import * as React from 'react';
|
|
|
2
2
|
|
|
3
3
|
import type { TranslationBundle } from '@jupyterlab/translation';
|
|
4
4
|
|
|
5
|
+
import type { ImageDiffViewMode } from './diffPreferences';
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* xtralab's image diff, registered in place of `@jupyterlab/git:image-diff`.
|
|
7
9
|
* Both sides arrive base64-encoded through the same `content()` getters used
|
|
@@ -39,30 +41,6 @@ export function imageDataType(path: string): string | null {
|
|
|
39
41
|
return IMAGE_DATA_TYPES[lower.slice(dot)] ?? null;
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
type ImageDiffViewMode = '2-up' | 'swipe' | 'onion';
|
|
43
|
-
|
|
44
|
-
const IMAGE_DIFF_VIEW_MODE_STORAGE_KEY = 'xtralab:image-diff-view-mode';
|
|
45
|
-
|
|
46
|
-
function readStoredImageViewMode(): ImageDiffViewMode {
|
|
47
|
-
try {
|
|
48
|
-
const raw = window.localStorage.getItem(IMAGE_DIFF_VIEW_MODE_STORAGE_KEY);
|
|
49
|
-
if (raw === '2-up' || raw === 'swipe' || raw === 'onion') {
|
|
50
|
-
return raw;
|
|
51
|
-
}
|
|
52
|
-
} catch {
|
|
53
|
-
// localStorage can throw in privacy/sandboxed contexts.
|
|
54
|
-
}
|
|
55
|
-
return '2-up';
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function writeStoredImageViewMode(mode: ImageDiffViewMode): void {
|
|
59
|
-
try {
|
|
60
|
-
window.localStorage.setItem(IMAGE_DIFF_VIEW_MODE_STORAGE_KEY, mode);
|
|
61
|
-
} catch {
|
|
62
|
-
// Best-effort.
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
44
|
/**
|
|
67
45
|
* Strip whitespace from a base64 payload: the server's `base64.encodebytes`
|
|
68
46
|
* inserts newlines some browsers reject in `data:` URLs, and the cleaned
|
|
@@ -143,6 +121,14 @@ interface IImageDiffViewProps {
|
|
|
143
121
|
* MIME subtype from {@link imageDataType}.
|
|
144
122
|
*/
|
|
145
123
|
fileType: string;
|
|
124
|
+
/**
|
|
125
|
+
* The selected comparison mode (host-controlled).
|
|
126
|
+
*/
|
|
127
|
+
mode: ImageDiffViewMode;
|
|
128
|
+
/**
|
|
129
|
+
* Called when the user picks another comparison mode.
|
|
130
|
+
*/
|
|
131
|
+
onModeChange: (mode: ImageDiffViewMode) => void;
|
|
146
132
|
/**
|
|
147
133
|
* Translation bundle for user-facing strings.
|
|
148
134
|
*/
|
|
@@ -154,7 +140,7 @@ interface IImageDiffViewProps {
|
|
|
154
140
|
* segmented-control styling) plus the selected 2-up / swipe / onion view.
|
|
155
141
|
*/
|
|
156
142
|
export function ImageDiffView(props: IImageDiffViewProps): React.ReactElement {
|
|
157
|
-
const { reference, challenger, fileType, trans } = props;
|
|
143
|
+
const { reference, challenger, fileType, mode, onModeChange, trans } = props;
|
|
158
144
|
const ref = React.useMemo(
|
|
159
145
|
() => toSide(reference, fileType),
|
|
160
146
|
[reference, fileType]
|
|
@@ -164,14 +150,6 @@ export function ImageDiffView(props: IImageDiffViewProps): React.ReactElement {
|
|
|
164
150
|
[challenger, fileType]
|
|
165
151
|
);
|
|
166
152
|
|
|
167
|
-
const [mode, setMode] = React.useState<ImageDiffViewMode>(() =>
|
|
168
|
-
readStoredImageViewMode()
|
|
169
|
-
);
|
|
170
|
-
const changeMode = React.useCallback((next: ImageDiffViewMode) => {
|
|
171
|
-
setMode(next);
|
|
172
|
-
writeStoredImageViewMode(next);
|
|
173
|
-
}, []);
|
|
174
|
-
|
|
175
153
|
return (
|
|
176
154
|
<div className="jp-xtralab-ImageDiff">
|
|
177
155
|
<div className="jp-xtralab-ImageDiff-header">
|
|
@@ -194,7 +172,7 @@ export function ImageDiffView(props: IImageDiffViewProps): React.ReactElement {
|
|
|
194
172
|
aria-selected={mode === value}
|
|
195
173
|
data-active={mode === value}
|
|
196
174
|
className="jp-xtralab-DiffWidget-segmentedButton"
|
|
197
|
-
onClick={() =>
|
|
175
|
+
onClick={() => onModeChange(value)}
|
|
198
176
|
>
|
|
199
177
|
{label}
|
|
200
178
|
</button>
|
package/src/git/index.ts
CHANGED
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
} from '@jupyterlab/application';
|
|
5
5
|
import { IThemeManager, WidgetTracker } from '@jupyterlab/apputils';
|
|
6
6
|
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
7
|
+
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
8
|
+
import { IStateDB } from '@jupyterlab/statedb';
|
|
7
9
|
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
8
10
|
|
|
9
11
|
import { IAskAgent } from '../askAgent/tokens';
|
|
@@ -16,12 +18,50 @@ import {
|
|
|
16
18
|
pinnedDiffWidgetId,
|
|
17
19
|
registerGitCommands
|
|
18
20
|
} from './commands';
|
|
21
|
+
import { DiffPreferences, IDiffPreferences } from './diffPreferences';
|
|
19
22
|
import diffProviderPlugin from './diffProvider';
|
|
20
23
|
import { IFileChange } from './tokens';
|
|
21
24
|
|
|
22
25
|
const GIT_DIFF_COMMAND_PLUGIN_ID = 'xtralab:git-diff-command';
|
|
26
|
+
const GIT_DIFF_PREFERENCES_PLUGIN_ID = 'xtralab:git-diff-preferences';
|
|
23
27
|
const GIT_DIFF_TRACKER_NAMESPACE = 'xtralab-git-diff';
|
|
24
28
|
|
|
29
|
+
/**
|
|
30
|
+
* The display choices shared by the launcher diff and the Git panel diff.
|
|
31
|
+
*/
|
|
32
|
+
const diffPreferencesPlugin: JupyterFrontEndPlugin<IDiffPreferences> = {
|
|
33
|
+
id: GIT_DIFF_PREFERENCES_PLUGIN_ID,
|
|
34
|
+
description:
|
|
35
|
+
'Keeps the git diff display choices in the settings and the state database.',
|
|
36
|
+
autoStart: true,
|
|
37
|
+
provides: IDiffPreferences,
|
|
38
|
+
optional: [ISettingRegistry, IStateDB],
|
|
39
|
+
activate: (
|
|
40
|
+
app: JupyterFrontEnd,
|
|
41
|
+
settingRegistry: ISettingRegistry | null,
|
|
42
|
+
state: IStateDB | null
|
|
43
|
+
): IDiffPreferences => {
|
|
44
|
+
const preferences = new DiffPreferences();
|
|
45
|
+
if (settingRegistry !== null) {
|
|
46
|
+
settingRegistry
|
|
47
|
+
.load(GIT_DIFF_PREFERENCES_PLUGIN_ID)
|
|
48
|
+
.then(settings => preferences.connectSettings(settings))
|
|
49
|
+
.catch(reason => {
|
|
50
|
+
console.error(
|
|
51
|
+
`xtralab: failed to load settings for ${GIT_DIFF_PREFERENCES_PLUGIN_ID}`,
|
|
52
|
+
reason
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (state !== null) {
|
|
57
|
+
preferences.connectState(state).catch(reason => {
|
|
58
|
+
console.error('xtralab: failed to restore the diff split', reason);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return preferences;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
25
65
|
/**
|
|
26
66
|
* The launcher's git diff command plugin. The upstream git panel stays
|
|
27
67
|
* enabled; this only adds `xtralab:git:open-diff` and preview/pinned-tab
|
|
@@ -32,13 +72,20 @@ const diffCommandPlugin: JupyterFrontEndPlugin<void> = {
|
|
|
32
72
|
description:
|
|
33
73
|
"The launcher dashboard's side-by-side git diff command, powered by @pierre/diffs.",
|
|
34
74
|
autoStart: true,
|
|
35
|
-
optional: [
|
|
75
|
+
optional: [
|
|
76
|
+
IThemeManager,
|
|
77
|
+
IRenderMimeRegistry,
|
|
78
|
+
ITranslator,
|
|
79
|
+
IAskAgent,
|
|
80
|
+
IDiffPreferences
|
|
81
|
+
],
|
|
36
82
|
activate: (
|
|
37
83
|
app: JupyterFrontEnd,
|
|
38
84
|
themeManager: IThemeManager | null,
|
|
39
85
|
rendermime: IRenderMimeRegistry | null,
|
|
40
86
|
translator: ITranslator | null,
|
|
41
|
-
askAgent: IAskAgent | null
|
|
87
|
+
askAgent: IAskAgent | null,
|
|
88
|
+
preferences: IDiffPreferences | null
|
|
42
89
|
): void => {
|
|
43
90
|
const trans = (translator ?? nullTranslator).load('jupyterlab');
|
|
44
91
|
const tracker = new WidgetTracker<DiffMainAreaWidget>({
|
|
@@ -62,6 +109,7 @@ const diffCommandPlugin: JupyterFrontEndPlugin<void> = {
|
|
|
62
109
|
contentsManager: app.serviceManager.contents,
|
|
63
110
|
rendermime,
|
|
64
111
|
askAgent,
|
|
112
|
+
preferences: preferences ?? new DiffPreferences(),
|
|
65
113
|
trans,
|
|
66
114
|
trackDiff: widget => tracker.add(widget),
|
|
67
115
|
onPinned: current => {
|
|
@@ -85,6 +133,7 @@ const diffCommandPlugin: JupyterFrontEndPlugin<void> = {
|
|
|
85
133
|
};
|
|
86
134
|
|
|
87
135
|
const plugins: JupyterFrontEndPlugin<unknown>[] = [
|
|
136
|
+
diffPreferencesPlugin,
|
|
88
137
|
diffCommandPlugin,
|
|
89
138
|
diffProviderPlugin
|
|
90
139
|
];
|
package/src/git/notebookDiff.tsx
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
type FileDiffMetadata
|
|
14
14
|
} from '@pierre/diffs';
|
|
15
15
|
|
|
16
|
-
import { resolveDiffTheme } from './diffTheme';
|
|
16
|
+
import { DIFF_SCROLLBAR_CSS, resolveDiffTheme } from './diffTheme';
|
|
17
17
|
|
|
18
18
|
const NOTEBOOK_DIFF_CSS_CLASS = 'jp-xtralab-NotebookDiff';
|
|
19
19
|
|
|
@@ -560,7 +560,8 @@ function diffLibraryOptions(theme: DiffsThemeNames, dark: boolean) {
|
|
|
560
560
|
diffStyle: 'split' as const,
|
|
561
561
|
disableFileHeader: true,
|
|
562
562
|
theme,
|
|
563
|
-
themeType: dark ? ('dark' as const) : ('light' as const)
|
|
563
|
+
themeType: dark ? ('dark' as const) : ('light' as const),
|
|
564
|
+
unsafeCSS: DIFF_SCROLLBAR_CSS
|
|
564
565
|
};
|
|
565
566
|
}
|
|
566
567
|
|
package/style/git.css
CHANGED
|
@@ -50,13 +50,15 @@
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
.jp-xtralab-DiffWidget-viewModeToolbarItem,
|
|
53
|
-
.jp-xtralab-DiffWidget-diffStyleToolbarItem
|
|
53
|
+
.jp-xtralab-DiffWidget-diffStyleToolbarItem,
|
|
54
|
+
.jp-xtralab-DiffWidget-lineWrapToolbarItem {
|
|
54
55
|
display: flex;
|
|
55
56
|
align-items: center;
|
|
56
57
|
font-size: var(--jp-ui-font-size0);
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
.jp-xtralab-DiffWidget-diffStyleToolbarItem
|
|
60
|
+
.jp-xtralab-DiffWidget-diffStyleToolbarItem,
|
|
61
|
+
.jp-xtralab-DiffWidget-lineWrapToolbarItem {
|
|
60
62
|
margin-left: 4px;
|
|
61
63
|
}
|
|
62
64
|
|