@difizen/libro-core 0.1.18 → 0.1.20

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.
Files changed (36) hide show
  1. package/es/cell/libro-cell-view.js +2 -2
  2. package/es/command/document-commands.d.ts.map +1 -1
  3. package/es/command/document-commands.js +6 -1
  4. package/es/command/libro-command-contribution.d.ts.map +1 -1
  5. package/es/command/libro-command-contribution.js +75 -45
  6. package/es/components/dnd-component/default-dnd-content.d.ts.map +1 -1
  7. package/es/components/dnd-component/default-dnd-content.js +3 -24
  8. package/es/components/libro-virtualized-render.js +1 -1
  9. package/es/libro-model.d.ts +7 -8
  10. package/es/libro-model.d.ts.map +1 -1
  11. package/es/libro-model.js +32 -21
  12. package/es/libro-protocol.d.ts +28 -6
  13. package/es/libro-protocol.d.ts.map +1 -1
  14. package/es/libro-service.d.ts +36 -3
  15. package/es/libro-service.d.ts.map +1 -1
  16. package/es/libro-service.js +97 -2
  17. package/es/libro-view.d.ts +5 -0
  18. package/es/libro-view.d.ts.map +1 -1
  19. package/es/libro-view.js +26 -61
  20. package/es/toolbar/libro-toolbar.d.ts.map +1 -1
  21. package/es/toolbar/libro-toolbar.js +16 -0
  22. package/es/virtualized-manager.d.ts +4 -0
  23. package/es/virtualized-manager.d.ts.map +1 -1
  24. package/es/virtualized-manager.js +7 -3
  25. package/package.json +5 -5
  26. package/src/cell/libro-cell-view.tsx +2 -2
  27. package/src/command/document-commands.ts +6 -1
  28. package/src/command/libro-command-contribution.ts +20 -1
  29. package/src/components/dnd-component/default-dnd-content.tsx +3 -19
  30. package/src/components/libro-virtualized-render.tsx +1 -1
  31. package/src/libro-model.ts +27 -20
  32. package/src/libro-protocol.ts +31 -8
  33. package/src/libro-service.ts +109 -3
  34. package/src/libro-view.tsx +22 -46
  35. package/src/toolbar/libro-toolbar.tsx +13 -0
  36. package/src/virtualized-manager.ts +14 -1
@@ -23,7 +23,6 @@ import type { CellView, DndContentProps } from '../../libro-protocol.js';
23
23
  import { MultiSelectionWhenShiftClick } from '../../libro-setting.js';
24
24
  import type { LibroView } from '../../libro-view.js';
25
25
  import { HolderOutlined, PlusOutlined } from '../../material-from-designer.js';
26
- import { VirtualizedManagerHelper } from '../../virtualized-manager-helper.js';
27
26
  import { BetweenCellProvider } from '../cell-protocol.js';
28
27
 
29
28
  export interface Dragparams {
@@ -39,8 +38,6 @@ export const DndCellContainer: React.FC<DndContentProps> = ({ cell, index }) =>
39
38
  );
40
39
  const BetweenCellContent = useInject<BetweenCellProvider>(BetweenCellProvider);
41
40
  const cellService = useInject<CellService>(LibroCellService);
42
- const virtualizedManagerHelper = useInject(VirtualizedManagerHelper);
43
- const virtualizedManager = virtualizedManagerHelper.getOrCreate(cell.parent.model);
44
41
  const dragDropManager = useDragDropManager();
45
42
  const dragDropMonitor = dragDropManager.getMonitor();
46
43
  const ItemRender = getOrigin(instance.dndItemRender);
@@ -237,31 +234,18 @@ export const DndCellContainer: React.FC<DndContentProps> = ({ cell, index }) =>
237
234
  }
238
235
  if (isDragInSelections) {
239
236
  instance.model.exchangeCells(instance.model.selections, dropIndex);
240
- if (virtualizedManager.isVirtualized) {
241
- instance.model.scrollToCellView({ cellIndex: dropIndex });
242
- } else {
243
- instance.model.scrollToView(cell);
244
- }
237
+ instance.model.scrollToView(cell);
245
238
 
246
239
  return;
247
240
  }
248
241
  }
249
242
  if (dragIndex < dropIndex) {
250
243
  instance.model.exchangeCell(dragIndex, dropIndex - 1);
251
-
252
- if (virtualizedManager.isVirtualized) {
253
- instance.model.scrollToCellView({ cellIndex: dropIndex });
254
- } else {
255
- instance.model.scrollToView(cell);
256
- }
244
+ instance.model.scrollToView(cell);
257
245
  }
258
246
  if (dragIndex > dropIndex) {
259
247
  instance.model.exchangeCell(dragIndex, dropIndex);
260
- if (virtualizedManager.isVirtualized) {
261
- instance.model.scrollToCellView({ cellIndex: dropIndex });
262
- } else {
263
- instance.model.scrollToView(cell);
264
- }
248
+ instance.model.scrollToView(cell);
265
249
  }
266
250
  }
267
251
  return;
@@ -95,7 +95,7 @@ export const LibroCellsOutputRender: React.FC<{
95
95
 
96
96
  libroView.model.onScrollToCellView((params: ScrollParams) => {
97
97
  // listRef.current!.scrollToRow(index);
98
- listRef.current!.scrollToLine(params.cellIndex, params.lineIndex || 1);
98
+ listRef.current!.scrollToCellPosition(params.cellIndex, params.cellOffset);
99
99
  });
100
100
  return () => {
101
101
  libroView.model.disposeScrollToCellViewEmitter();
@@ -26,6 +26,7 @@ import type {
26
26
  ScrollParams,
27
27
  CellView,
28
28
  MouseMode,
29
+ ICellContentChange,
29
30
  } from './libro-protocol.js';
30
31
  import { EnterEditModeWhenAddCell } from './libro-setting.js';
31
32
  import { VirtualizedManagerHelper } from './virtualized-manager-helper.js';
@@ -47,10 +48,6 @@ export class LibroModel implements NotebookModel, DndListModel {
47
48
  return this.cellViewChangeEmitter.event;
48
49
  }
49
50
 
50
- scrollToCellView = (params: ScrollParams) => {
51
- this.scrollToCellViewEmitter.fire(params);
52
- };
53
-
54
51
  disposeScrollToCellViewEmitter() {
55
52
  this.scrollToCellViewEmitter.dispose();
56
53
  }
@@ -60,9 +57,9 @@ export class LibroModel implements NotebookModel, DndListModel {
60
57
  return this.onCommandModeChangedEmitter.event;
61
58
  }
62
59
 
63
- protected onContentChangedEmitter: Emitter<boolean> = new Emitter();
64
- get onContentChanged() {
65
- return this.onContentChangedEmitter.event;
60
+ protected onChangedEmitter: Emitter<boolean> = new Emitter();
61
+ get onChanged() {
62
+ return this.onChangedEmitter.event;
66
63
  }
67
64
 
68
65
  protected onSourceChangedEmitter: Emitter<boolean> = new Emitter();
@@ -70,6 +67,15 @@ export class LibroModel implements NotebookModel, DndListModel {
70
67
  return this.onSourceChangedEmitter.event;
71
68
  }
72
69
 
70
+ protected onCellContentChangedEmitter: Emitter<ICellContentChange> = new Emitter();
71
+ get onCellContentChanged() {
72
+ return this.onCellContentChangedEmitter.event;
73
+ }
74
+
75
+ onCellContentChange(change: ICellContentChange) {
76
+ this.onCellContentChangedEmitter.fire(change);
77
+ }
78
+
73
79
  id: string;
74
80
 
75
81
  /**
@@ -219,9 +225,10 @@ export class LibroModel implements NotebookModel, DndListModel {
219
225
  insert: { index: currpos, cells: cellViews },
220
226
  });
221
227
  } else if (delta.delete !== null && delta.delete !== undefined) {
228
+ const cellViews = this.cells.slice(currpos, currpos + delta.delete);
222
229
  this.removeRange(currpos, currpos + delta.delete);
223
230
  this.cellViewChangeEmitter.fire({
224
- delete: { index: currpos, number: delta.delete },
231
+ delete: { index: currpos, number: delta.delete, cells: cellViews },
225
232
  });
226
233
  } else if (delta.retain !== null && delta.retain !== undefined) {
227
234
  currpos += delta.retain;
@@ -290,12 +297,9 @@ export class LibroModel implements NotebookModel, DndListModel {
290
297
  });
291
298
  }
292
299
 
293
- /**
294
- * cell list change or cell content change
295
- */
296
300
  onChange() {
297
301
  this.dirty = true;
298
- this.onContentChangedEmitter.fire(true);
302
+ this.onChangedEmitter.fire(true);
299
303
  }
300
304
 
301
305
  onSourceChange() {
@@ -361,13 +365,21 @@ export class LibroModel implements NotebookModel, DndListModel {
361
365
  /**
362
366
  * 自动滚动到可视范围内
363
367
  */
364
- scrollToView(cell: CellView) {
368
+ scrollToView(cell: CellView, cellOffset = 0) {
369
+ const virtualizedManager = this.virtualizedManagerHelper.getOrCreate(this);
370
+ if (virtualizedManager.isVirtualized) {
371
+ const cellIndex = this.cells.findIndex((_cell) => _cell.id === cell.id);
372
+ this.scrollToCellViewEmitter.fire({ cellIndex, cellOffset });
373
+ return;
374
+ }
375
+
365
376
  let target = document.getElementById(cell.id);
366
377
  if (!target) {
367
378
  return;
368
379
  }
380
+
369
381
  const _targetheight = target?.offsetHeight || 0;
370
- let offsetTop = target?.offsetTop || 0;
382
+ let offsetTop = (target?.offsetTop || 0) + cellOffset;
371
383
  while (
372
384
  target?.offsetParent &&
373
385
  !target?.offsetParent?.className?.includes('libro-view-content-left')
@@ -622,14 +634,9 @@ export class LibroModel implements NotebookModel, DndListModel {
622
634
  cells.splice(sourceIndex, 1);
623
635
  cells.splice(targetIndex, 0, sourceItem);
624
636
  this.cells = cells;
625
- const virtualizedManager = this.virtualizedManagerHelper.getOrCreate(this);
626
637
  setTimeout(() => {
627
638
  // 上下移动也需要调整可视区域范围
628
- if (virtualizedManager.isVirtualized) {
629
- this.scrollToCellView({ cellIndex: sourceIndex });
630
- } else {
631
- this.scrollToView(sourceItem);
632
- }
639
+ this.scrollToView(sourceItem);
633
640
  }, 300);
634
641
  return true;
635
642
  }
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/unified-signatures */
2
- import type { IModel } from '@difizen/libro-code-editor';
2
+ import type { IModel, IModelContentChange } from '@difizen/libro-code-editor';
3
3
  import type {
4
4
  CellType,
5
5
  ICell,
@@ -60,10 +60,15 @@ export type Options = {
60
60
 
61
61
  export interface ScrollParams {
62
62
  cellIndex: number;
63
- lineIndex?: number;
63
+ cellOffset?: number;
64
64
  }
65
65
 
66
66
  export type NotebookModel = BaseNotebookModel & DndListModel;
67
+
68
+ export interface ICellContentChange {
69
+ cell: CellView;
70
+ changes: IModelContentChange[];
71
+ }
67
72
  export interface BaseNotebookModel {
68
73
  id: string;
69
74
  /**
@@ -98,12 +103,26 @@ export interface BaseNotebookModel {
98
103
 
99
104
  onCommandModeChanged: Event<boolean>;
100
105
 
101
- onContentChanged: Event<boolean>;
106
+ /**
107
+ * all changes
108
+ */
109
+ onChanged: Event<boolean>;
102
110
 
111
+ /**
112
+ * cell content & type
113
+ */
103
114
  onSourceChanged: Event<boolean>;
104
115
 
116
+ /**
117
+ * cell create & delete
118
+ */
105
119
  onCellViewChanged: Event<CellViewChange>;
106
120
 
121
+ /**
122
+ * cell content change detail
123
+ */
124
+ onCellContentChanged: Event<ICellContentChange>;
125
+
107
126
  getCells: () => CellView[];
108
127
 
109
128
  /**
@@ -171,9 +190,15 @@ export interface BaseNotebookModel {
171
190
 
172
191
  enterEditMode?: () => void;
173
192
 
193
+ /**
194
+ * all changes: cell value\cell type\cell output\ cell executecount\ cell or notebook metadata\cell create & delete
195
+ * @returns
196
+ */
174
197
  onChange?: () => void;
175
198
 
176
- onSourceChange?: () => void;
199
+ onSourceChange?: (cells: CellView[]) => void;
200
+
201
+ onCellContentChange: (changes: ICellContentChange) => void;
177
202
 
178
203
  interrupt?: () => void;
179
204
 
@@ -189,7 +214,7 @@ export interface BaseNotebookModel {
189
214
 
190
215
  readonly sharedModel: ISharedNotebook;
191
216
 
192
- scrollToView: (cell: CellView) => void;
217
+ scrollToView: (cell: CellView, cellOffset?: number) => void;
193
218
 
194
219
  customParams: Record<string, any>;
195
220
  getCustomKey: (key: string) => any;
@@ -199,8 +224,6 @@ export interface BaseNotebookModel {
199
224
 
200
225
  onScrollToCellView: Event<ScrollParams>;
201
226
 
202
- scrollToCellView: (params: ScrollParams) => void;
203
-
204
227
  disposeScrollToCellViewEmitter: () => void;
205
228
  }
206
229
 
@@ -290,7 +313,7 @@ export interface CellViewOptions {
290
313
 
291
314
  export interface CellViewChange {
292
315
  insert?: { cells: CellView[]; index: number };
293
- delete?: { index: number; number: number };
316
+ delete?: { index: number; number: number; cells: CellView[] };
294
317
  }
295
318
 
296
319
  export interface CellModel extends IModel, Disposable {
@@ -1,9 +1,15 @@
1
- import { Emitter } from '@difizen/mana-app';
1
+ import type { Disposable } from '@difizen/mana-app';
2
+ import { DisposableCollection, Emitter } from '@difizen/mana-app';
2
3
  import { ThemeService, ViewManager } from '@difizen/mana-app';
3
4
  import { inject, singleton } from '@difizen/mana-app';
4
5
  import { prop } from '@difizen/mana-app';
5
6
 
6
- import type { NotebookOption, NotebookView } from './libro-protocol.js';
7
+ import type {
8
+ CellView,
9
+ ICellContentChange,
10
+ NotebookOption,
11
+ NotebookView,
12
+ } from './libro-protocol.js';
7
13
  import {
8
14
  notebookViewFactoryId,
9
15
  ModelFactory,
@@ -11,8 +17,24 @@ import {
11
17
  } from './libro-protocol.js';
12
18
  import { LibroViewTracker } from './libro-view-tracker.js';
13
19
 
20
+ export interface NotebookViewChange {
21
+ libroView: NotebookView;
22
+ contentChanges: Array<{
23
+ range: {
24
+ start: number;
25
+ end: number;
26
+ };
27
+ addedCells: CellView[];
28
+ removedCells: CellView[];
29
+ }>;
30
+ cellChanges: Array<{
31
+ cell: CellView;
32
+ }>;
33
+ }
34
+
14
35
  @singleton({ contrib: NotebookService })
15
- export class LibroService implements NotebookService {
36
+ export class LibroService implements NotebookService, Disposable {
37
+ protected toDispose = new DisposableCollection();
16
38
  @inject(ModelFactory) protected libroModelFactory: ModelFactory;
17
39
  @inject(ViewManager) protected viewManager: ViewManager;
18
40
  @inject(LibroViewTracker) protected libroViewTracker: LibroViewTracker;
@@ -50,6 +72,34 @@ export class LibroService implements NotebookService {
50
72
  get onNotebookViewCreated() {
51
73
  return this.onNotebookViewCreatedEmitter.event;
52
74
  }
75
+ protected onNotebookViewSavedEmitter: Emitter<NotebookView> = new Emitter();
76
+ get onNotebookViewSaved() {
77
+ return this.onNotebookViewSavedEmitter.event;
78
+ }
79
+ protected onNotebookViewChangedEmitter: Emitter<NotebookViewChange> = new Emitter();
80
+ get onNotebookViewChanged() {
81
+ return this.onNotebookViewChangedEmitter.event;
82
+ }
83
+ protected onNotebookViewClosedEmitter: Emitter<NotebookView> = new Emitter();
84
+ get onNotebookViewClosed() {
85
+ return this.onNotebookViewClosedEmitter.event;
86
+ }
87
+ protected onNotebookCellCreatedEmitter: Emitter<CellView[]> = new Emitter();
88
+ get onNotebookCellCreated() {
89
+ return this.onNotebookCellCreatedEmitter.event;
90
+ }
91
+ protected onNotebookCellSavedEmitter: Emitter<CellView[]> = new Emitter();
92
+ get onNotebookCellSaved() {
93
+ return this.onNotebookCellSavedEmitter.event;
94
+ }
95
+ protected onNotebookCellChangedEmitter: Emitter<ICellContentChange> = new Emitter();
96
+ get onNotebookCellChanged() {
97
+ return this.onNotebookCellChangedEmitter.event;
98
+ }
99
+ protected onNotebookCellDeletedEmitter: Emitter<CellView[]> = new Emitter();
100
+ get onNotebookCellDeleted() {
101
+ return this.onNotebookCellDeletedEmitter.event;
102
+ }
53
103
 
54
104
  get focus(): NotebookView | undefined {
55
105
  return this._focus;
@@ -68,6 +118,7 @@ export class LibroService implements NotebookService {
68
118
  }
69
119
 
70
120
  deleteLibroViewFromCache(instance: NotebookView) {
121
+ this.onNotebookViewClosedEmitter.fire(instance);
71
122
  this.libroViewTracker.viewCache.delete(instance.id);
72
123
  this.libroViewTracker.modelCache.delete(instance.model.id);
73
124
  }
@@ -98,6 +149,52 @@ export class LibroService implements NotebookService {
98
149
  const notebookView = await notebookViewPromise;
99
150
  this.libroViewTracker.viewCache.set(notebookView.id, notebookView);
100
151
  this.onNotebookViewCreatedEmitter.fire(notebookView);
152
+ this.toDispose.push(
153
+ notebookView.onSave(() => {
154
+ this.onNotebookViewSavedEmitter.fire(notebookView);
155
+ }),
156
+ );
157
+ this.toDispose.push(
158
+ notebookView.model.onCellContentChanged((e) => {
159
+ this.onNotebookCellChangedEmitter.fire(e);
160
+ }),
161
+ );
162
+ this.toDispose.push(
163
+ notebookView.model.onCellViewChanged((e) => {
164
+ const changes: NotebookViewChange = {
165
+ libroView: notebookView,
166
+ cellChanges: [],
167
+ contentChanges: [],
168
+ };
169
+
170
+ if (e.delete) {
171
+ changes.contentChanges.push({
172
+ range: {
173
+ start: e.delete.index,
174
+ end: e.delete.index + e.delete?.number,
175
+ },
176
+ removedCells: e.delete.cells,
177
+ addedCells: [],
178
+ });
179
+ this.onNotebookCellDeletedEmitter.fire(e.delete.cells);
180
+ }
181
+
182
+ if (e.insert) {
183
+ changes.contentChanges.push({
184
+ range: {
185
+ start: e.insert.index,
186
+ end: e.insert.index + e.insert?.cells.length,
187
+ },
188
+ removedCells: [],
189
+ addedCells: e.insert.cells,
190
+ });
191
+ this.onNotebookCellCreatedEmitter.fire(e.insert.cells);
192
+ }
193
+
194
+ this.onNotebookViewChangedEmitter.fire(changes);
195
+ }),
196
+ );
197
+
101
198
  return notebookViewPromise;
102
199
  }
103
200
 
@@ -109,4 +206,13 @@ export class LibroService implements NotebookService {
109
206
  setHasFocus(hasFocus: boolean): void {
110
207
  this._hasFocus = hasFocus;
111
208
  }
209
+
210
+ protected isDisposed = false;
211
+ get disposed() {
212
+ return this.isDisposed;
213
+ }
214
+ dispose() {
215
+ this.toDispose.dispose();
216
+ this.isDisposed = true;
217
+ }
112
218
  }
@@ -1,4 +1,5 @@
1
1
  import { ToTopOutlined } from '@ant-design/icons';
2
+ import type { IModelContentChange } from '@difizen/libro-code-editor';
2
3
  import {
3
4
  concatMultilineString,
4
5
  copy2clipboard,
@@ -281,6 +282,10 @@ export class LibroView extends BaseView implements NotebookView {
281
282
  get onCellCreate() {
282
283
  return this.onCellCreateEmitter.event;
283
284
  }
285
+ protected onCellDeleteEmitter: Emitter<CellView> = new Emitter();
286
+ get onCellDelete() {
287
+ return this.onCellDeleteEmitter.event;
288
+ }
284
289
 
285
290
  onBlurEmitter: Emitter = new Emitter();
286
291
  get onBlur() {
@@ -318,6 +323,10 @@ export class LibroView extends BaseView implements NotebookView {
318
323
  get onSave() {
319
324
  return this.onSaveEmitter.event;
320
325
  }
326
+ onCellContentChangedEmitter: Emitter<IModelContentChange[]> = new Emitter();
327
+ get onCellContentChanged() {
328
+ return this.onCellContentChangedEmitter.event;
329
+ }
321
330
 
322
331
  runCellEmitter: Emitter<CellView> = new Emitter();
323
332
  get onRunCell() {
@@ -411,7 +420,6 @@ export class LibroView extends BaseView implements NotebookView {
411
420
  this.toDispose.push(
412
421
  watch(this.model, 'cells', () => {
413
422
  this.model.onChange?.();
414
- this.model.onSourceChange?.();
415
423
  }),
416
424
  );
417
425
  this.initializedDefer.resolve();
@@ -657,18 +665,11 @@ export class LibroView extends BaseView implements NotebookView {
657
665
  }
658
666
  this.runCells([cell]);
659
667
  }
660
- if (this.virtualizedManager.isVirtualized) {
661
- // 通过用户反馈,这里跳动会严重影响体验
662
- // setTimeout(() => {
663
- // if (this.activeCell) this.model.scrollToCellView({ cellIndex: this.activeCellIndex });
664
- // });
665
- } else {
666
- setTimeout(() => {
667
- if (this.activeCell) {
668
- this.model.scrollToView(this.activeCell);
669
- }
670
- });
671
- }
668
+ setTimeout(() => {
669
+ if (this.activeCell) {
670
+ this.model.scrollToView(this.activeCell);
671
+ }
672
+ });
672
673
  };
673
674
 
674
675
  runCellandInsertBelow = async (cell: CellView) => {
@@ -908,9 +909,8 @@ export class LibroView extends BaseView implements NotebookView {
908
909
  };
909
910
 
910
911
  clearAllOutputs = () => {
911
- if (this.virtualizedManager.isVirtualized) {
912
- this.model.scrollToCellView({ cellIndex: 0 });
913
- } // 清空所有 cell滚动到最上面
912
+ // 清空所有 cell滚动到最上面
913
+ this.model.scrollToView(this.model.cells[0]);
914
914
  for (const cell of this.model.cells) {
915
915
  if (ExecutableCellView.is(cell) && ExecutableCellModel.is(cell.model)) {
916
916
  cell.clearExecution();
@@ -1045,11 +1045,7 @@ export class LibroView extends BaseView implements NotebookView {
1045
1045
  if (this.findCellIndex(this.activeCell) > 0) {
1046
1046
  this.extendContiguousSelectionTo(activeIndex - 1);
1047
1047
  }
1048
- if (this.virtualizedManager.isVirtualized) {
1049
- this.model.scrollToCellView({ cellIndex: this.activeCellIndex });
1050
- } else {
1051
- this.model.scrollToView(this.activeCell);
1052
- }
1048
+ this.model.scrollToView(this.activeCell);
1053
1049
  }
1054
1050
  };
1055
1051
 
@@ -1058,11 +1054,7 @@ export class LibroView extends BaseView implements NotebookView {
1058
1054
  if (this.findCellIndex(this.activeCell) > 0) {
1059
1055
  this.extendContiguousSelectionTo(0);
1060
1056
  }
1061
- if (this.virtualizedManager.isVirtualized) {
1062
- this.model.scrollToCellView({ cellIndex: this.activeCellIndex });
1063
- } else {
1064
- this.model.scrollToView(this.activeCell);
1065
- }
1057
+ this.model.scrollToView(this.activeCell);
1066
1058
  }
1067
1059
  };
1068
1060
 
@@ -1076,11 +1068,7 @@ export class LibroView extends BaseView implements NotebookView {
1076
1068
  if (this.findCellIndex(this.activeCell) >= 0) {
1077
1069
  this.extendContiguousSelectionTo(activeIndex + 1);
1078
1070
  }
1079
- if (this.virtualizedManager.isVirtualized) {
1080
- this.model.scrollToCellView({ cellIndex: this.activeCellIndex });
1081
- } else {
1082
- this.model.scrollToView(this.activeCell);
1083
- }
1071
+ this.model.scrollToView(this.activeCell);
1084
1072
  }
1085
1073
  };
1086
1074
 
@@ -1089,11 +1077,7 @@ export class LibroView extends BaseView implements NotebookView {
1089
1077
  if (this.findCellIndex(this.activeCell) > 0) {
1090
1078
  this.extendContiguousSelectionTo(this.model.cells.length - 1);
1091
1079
  }
1092
- if (this.virtualizedManager.isVirtualized) {
1093
- this.model.scrollToCellView({ cellIndex: this.activeCellIndex });
1094
- } else {
1095
- this.model.scrollToView(this.activeCell);
1096
- }
1080
+ this.model.scrollToView(this.activeCell);
1097
1081
  }
1098
1082
  };
1099
1083
 
@@ -1262,11 +1246,7 @@ export class LibroView extends BaseView implements NotebookView {
1262
1246
  if (newSelectedCell) {
1263
1247
  this.model.selectCell(newSelectedCell);
1264
1248
  this.model.selections = [];
1265
- if (this.virtualizedManager.isVirtualized) {
1266
- this.model.scrollToCellView({ cellIndex: this.activeCellIndex });
1267
- } else {
1268
- this.model.scrollToView(newSelectedCell);
1269
- }
1249
+ this.model.scrollToView(newSelectedCell);
1270
1250
  }
1271
1251
  };
1272
1252
 
@@ -1275,11 +1255,7 @@ export class LibroView extends BaseView implements NotebookView {
1275
1255
  if (newSelectedCell) {
1276
1256
  this.model.selectCell(newSelectedCell);
1277
1257
  this.model.selections = [];
1278
- if (this.virtualizedManager.isVirtualized) {
1279
- this.model.scrollToCellView({ cellIndex: this.activeCellIndex });
1280
- } else {
1281
- this.model.scrollToView(newSelectedCell);
1282
- }
1258
+ this.model.scrollToView(newSelectedCell);
1283
1259
  }
1284
1260
  };
1285
1261
 
@@ -94,6 +94,19 @@ export class LibroToolbarContribution implements ToolbarContribution {
94
94
  group: ['group2'],
95
95
  order: 'c-all',
96
96
  });
97
+ registry.registerItem({
98
+ id: DocumentCommands['FormatCell'].id,
99
+ command: DocumentCommands['FormatCell'].id,
100
+ tooltip: (
101
+ <div className="libro-side-tooltip">
102
+ <span className="libro-tooltip-text">{l10n.t('格式化代码')}</span>
103
+ <span className="libro-tooltip-keybind">Shift+Option+F</span>
104
+ </div>
105
+ ),
106
+
107
+ group: ['sidetoolbar1'],
108
+ order: 'd',
109
+ });
97
110
  registry.registerItem({
98
111
  id: NotebookCommands['MoveCellUp'].id,
99
112
  command: NotebookCommands['MoveCellUp'].id,
@@ -1,4 +1,7 @@
1
- import { transient, prop } from '@difizen/mana-app';
1
+ import { transient, prop, inject } from '@difizen/mana-app';
2
+
3
+ import type { NotebookModel } from './libro-protocol.js';
4
+ import { VirtualizedManagerOption } from './libro-protocol.js';
2
5
 
3
6
  export interface IVirtualizedManager {
4
7
  openVirtualized: (length: number, size?: number, path?: string) => Promise<boolean>;
@@ -13,6 +16,16 @@ export class VirtualizedManager implements IVirtualizedManager {
13
16
  */
14
17
  @prop()
15
18
  isVirtualized = false;
19
+
20
+ libroModel: NotebookModel;
21
+
22
+ constructor(
23
+ @inject(VirtualizedManagerOption)
24
+ virtualizedManagerOption: VirtualizedManagerOption,
25
+ ) {
26
+ this.libroModel = virtualizedManagerOption.libroModel;
27
+ }
28
+
16
29
  /**
17
30
  *
18
31
  * @param length cell个数