@theia/notebook 1.46.1 → 1.47.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.
Files changed (117) hide show
  1. package/lib/browser/contributions/notebook-actions-contribution.d.ts +3 -1
  2. package/lib/browser/contributions/notebook-actions-contribution.d.ts.map +1 -1
  3. package/lib/browser/contributions/notebook-actions-contribution.js +38 -37
  4. package/lib/browser/contributions/notebook-actions-contribution.js.map +1 -1
  5. package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts +5 -1
  6. package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts.map +1 -1
  7. package/lib/browser/contributions/notebook-cell-actions-contribution.js +29 -36
  8. package/lib/browser/contributions/notebook-cell-actions-contribution.js.map +1 -1
  9. package/lib/browser/contributions/notebook-color-contribution.js +2 -7
  10. package/lib/browser/contributions/notebook-color-contribution.js.map +1 -1
  11. package/lib/browser/index.js +12 -21
  12. package/lib/browser/index.js.map +1 -1
  13. package/lib/browser/notebook-cell-resource-resolver.d.ts +10 -5
  14. package/lib/browser/notebook-cell-resource-resolver.d.ts.map +1 -1
  15. package/lib/browser/notebook-cell-resource-resolver.js +18 -17
  16. package/lib/browser/notebook-cell-resource-resolver.js.map +1 -1
  17. package/lib/browser/notebook-editor-widget-factory.js +10 -18
  18. package/lib/browser/notebook-editor-widget-factory.js.map +1 -1
  19. package/lib/browser/notebook-editor-widget.d.ts +20 -0
  20. package/lib/browser/notebook-editor-widget.d.ts.map +1 -1
  21. package/lib/browser/notebook-editor-widget.js +69 -32
  22. package/lib/browser/notebook-editor-widget.js.map +1 -1
  23. package/lib/browser/notebook-open-handler.js +4 -12
  24. package/lib/browser/notebook-open-handler.js.map +1 -1
  25. package/lib/browser/notebook-renderer-registry.d.ts +7 -0
  26. package/lib/browser/notebook-renderer-registry.d.ts.map +1 -1
  27. package/lib/browser/notebook-renderer-registry.js +13 -7
  28. package/lib/browser/notebook-renderer-registry.js.map +1 -1
  29. package/lib/browser/notebook-type-registry.js +2 -7
  30. package/lib/browser/notebook-type-registry.js.map +1 -1
  31. package/lib/browser/renderers/cell-output-webview.d.ts +2 -1
  32. package/lib/browser/renderers/cell-output-webview.d.ts.map +1 -1
  33. package/lib/browser/renderers/cell-output-webview.js.map +1 -1
  34. package/lib/browser/service/notebook-cell-context-manager.d.ts.map +1 -1
  35. package/lib/browser/service/notebook-cell-context-manager.js +6 -16
  36. package/lib/browser/service/notebook-cell-context-manager.js.map +1 -1
  37. package/lib/browser/service/notebook-editor-widget-service.js +8 -16
  38. package/lib/browser/service/notebook-editor-widget-service.js.map +1 -1
  39. package/lib/browser/service/notebook-execution-service.js +12 -20
  40. package/lib/browser/service/notebook-execution-service.js.map +1 -1
  41. package/lib/browser/service/notebook-execution-state-service.d.ts.map +1 -1
  42. package/lib/browser/service/notebook-execution-state-service.js +5 -14
  43. package/lib/browser/service/notebook-execution-state-service.js.map +1 -1
  44. package/lib/browser/service/notebook-kernel-history-service.js +12 -20
  45. package/lib/browser/service/notebook-kernel-history-service.js.map +1 -1
  46. package/lib/browser/service/notebook-kernel-quick-pick-service.js +12 -20
  47. package/lib/browser/service/notebook-kernel-quick-pick-service.js.map +1 -1
  48. package/lib/browser/service/notebook-kernel-service.d.ts +23 -12
  49. package/lib/browser/service/notebook-kernel-service.d.ts.map +1 -1
  50. package/lib/browser/service/notebook-kernel-service.js +11 -26
  51. package/lib/browser/service/notebook-kernel-service.js.map +1 -1
  52. package/lib/browser/service/notebook-model-resolver-service.d.ts +3 -2
  53. package/lib/browser/service/notebook-model-resolver-service.d.ts.map +1 -1
  54. package/lib/browser/service/notebook-model-resolver-service.js +21 -22
  55. package/lib/browser/service/notebook-model-resolver-service.js.map +1 -1
  56. package/lib/browser/service/notebook-renderer-messaging-service.d.ts +1 -0
  57. package/lib/browser/service/notebook-renderer-messaging-service.d.ts.map +1 -1
  58. package/lib/browser/service/notebook-renderer-messaging-service.js +12 -7
  59. package/lib/browser/service/notebook-renderer-messaging-service.js.map +1 -1
  60. package/lib/browser/service/notebook-service.d.ts +2 -2
  61. package/lib/browser/service/notebook-service.d.ts.map +1 -1
  62. package/lib/browser/service/notebook-service.js +13 -21
  63. package/lib/browser/service/notebook-service.js.map +1 -1
  64. package/lib/browser/view/notebook-cell-list-view.d.ts +3 -1
  65. package/lib/browser/view/notebook-cell-list-view.d.ts.map +1 -1
  66. package/lib/browser/view/notebook-cell-list-view.js +24 -7
  67. package/lib/browser/view/notebook-cell-list-view.js.map +1 -1
  68. package/lib/browser/view/notebook-cell-toolbar-factory.d.ts +1 -0
  69. package/lib/browser/view/notebook-cell-toolbar-factory.d.ts.map +1 -1
  70. package/lib/browser/view/notebook-cell-toolbar-factory.js +11 -18
  71. package/lib/browser/view/notebook-cell-toolbar-factory.js.map +1 -1
  72. package/lib/browser/view/notebook-cell-toolbar.js +2 -2
  73. package/lib/browser/view/notebook-cell-toolbar.js.map +1 -1
  74. package/lib/browser/view/notebook-code-cell-view.d.ts +6 -2
  75. package/lib/browser/view/notebook-code-cell-view.d.ts.map +1 -1
  76. package/lib/browser/view/notebook-code-cell-view.js +41 -30
  77. package/lib/browser/view/notebook-code-cell-view.js.map +1 -1
  78. package/lib/browser/view/notebook-main-toolbar.d.ts.map +1 -1
  79. package/lib/browser/view/notebook-main-toolbar.js +19 -22
  80. package/lib/browser/view/notebook-main-toolbar.js.map +1 -1
  81. package/lib/browser/view/notebook-markdown-cell-view.js +6 -14
  82. package/lib/browser/view/notebook-markdown-cell-view.js.map +1 -1
  83. package/lib/browser/view-model/notebook-cell-model.d.ts +1 -1
  84. package/lib/browser/view-model/notebook-cell-model.d.ts.map +1 -1
  85. package/lib/browser/view-model/notebook-cell-model.js +17 -22
  86. package/lib/browser/view-model/notebook-cell-model.js.map +1 -1
  87. package/lib/browser/view-model/notebook-model.d.ts +17 -14
  88. package/lib/browser/view-model/notebook-model.d.ts.map +1 -1
  89. package/lib/browser/view-model/notebook-model.js +30 -27
  90. package/lib/browser/view-model/notebook-model.js.map +1 -1
  91. package/lib/common/index.js +3 -12
  92. package/lib/common/index.js.map +1 -1
  93. package/lib/common/notebook-common.d.ts +1 -2
  94. package/lib/common/notebook-common.d.ts.map +1 -1
  95. package/lib/common/notebook-common.js.map +1 -1
  96. package/package.json +9 -8
  97. package/src/browser/contributions/notebook-actions-contribution.ts +41 -24
  98. package/src/browser/contributions/notebook-cell-actions-contribution.ts +24 -15
  99. package/src/browser/notebook-cell-resource-resolver.ts +24 -7
  100. package/src/browser/notebook-editor-widget.tsx +68 -6
  101. package/src/browser/notebook-renderer-registry.ts +19 -0
  102. package/src/browser/renderers/cell-output-webview.ts +2 -1
  103. package/src/browser/service/notebook-cell-context-manager.ts +0 -1
  104. package/src/browser/service/notebook-execution-state-service.ts +2 -3
  105. package/src/browser/service/notebook-kernel-service.ts +18 -21
  106. package/src/browser/service/notebook-model-resolver-service.ts +14 -10
  107. package/src/browser/service/notebook-renderer-messaging-service.ts +9 -1
  108. package/src/browser/service/notebook-service.ts +4 -4
  109. package/src/browser/style/index.css +17 -3
  110. package/src/browser/view/notebook-cell-list-view.tsx +34 -11
  111. package/src/browser/view/notebook-cell-toolbar-factory.tsx +2 -0
  112. package/src/browser/view/notebook-cell-toolbar.tsx +2 -2
  113. package/src/browser/view/notebook-code-cell-view.tsx +39 -14
  114. package/src/browser/view/notebook-main-toolbar.tsx +10 -4
  115. package/src/browser/view-model/notebook-cell-model.ts +5 -3
  116. package/src/browser/view-model/notebook-model.ts +27 -14
  117. package/src/common/notebook-common.ts +1 -2
@@ -16,7 +16,7 @@
16
16
 
17
17
  import * as React from '@theia/core/shared/react';
18
18
  import { CommandRegistry, MenuModelRegistry, URI } from '@theia/core';
19
- import { ReactWidget, Navigatable, SaveableSource, Message, DelegatingSaveable } from '@theia/core/lib/browser';
19
+ import { ReactWidget, Navigatable, SaveableSource, Message, DelegatingSaveable, lock, unlock } from '@theia/core/lib/browser';
20
20
  import { ReactNode } from '@theia/core/shared/react';
21
21
  import { CellKind } from '../common';
22
22
  import { CellRenderer as CellRenderer, NotebookCellListView } from './view/notebook-cell-list-view';
@@ -29,6 +29,9 @@ import { Emitter } from '@theia/core/shared/vscode-languageserver-protocol';
29
29
  import { NotebookEditorWidgetService } from './service/notebook-editor-widget-service';
30
30
  import { NotebookMainToolbarRenderer } from './view/notebook-main-toolbar';
31
31
  import { Deferred } from '@theia/core/lib/common/promise-util';
32
+ import { MarkdownString } from '@theia/core/lib/common/markdown-rendering';
33
+
34
+ const PerfectScrollbar = require('react-perfect-scrollbar');
32
35
 
33
36
  export const NotebookEditorWidgetContainerFactory = Symbol('NotebookEditorWidgetContainerFactory');
34
37
 
@@ -43,6 +46,11 @@ export function createNotebookEditorWidgetContainer(parent: interfaces.Container
43
46
 
44
47
  const NotebookEditorProps = Symbol('NotebookEditorProps');
45
48
 
49
+ interface RenderMessage {
50
+ rendererId: string;
51
+ message: unknown;
52
+ }
53
+
46
54
  export interface NotebookEditorProps {
47
55
  uri: URI,
48
56
  readonly notebookType: string,
@@ -81,6 +89,21 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
81
89
  protected readonly onDidChangeModelEmitter = new Emitter<void>();
82
90
  readonly onDidChangeModel = this.onDidChangeModelEmitter.event;
83
91
 
92
+ protected readonly onDidChangeReadOnlyEmitter = new Emitter<boolean | MarkdownString>();
93
+ readonly onDidChangeReadOnly = this.onDidChangeReadOnlyEmitter.event;
94
+
95
+ protected readonly onPostKernelMessageEmitter = new Emitter<unknown>();
96
+ readonly onPostKernelMessage = this.onPostKernelMessageEmitter.event;
97
+
98
+ protected readonly onDidPostKernelMessageEmitter = new Emitter<unknown>();
99
+ readonly onDidPostKernelMessage = this.onDidPostKernelMessageEmitter.event;
100
+
101
+ protected readonly onPostRendererMessageEmitter = new Emitter<RenderMessage>();
102
+ readonly onPostRendererMessage = this.onPostRendererMessageEmitter.event;
103
+
104
+ protected readonly onDidReceiveKernelMessageEmitter = new Emitter<unknown>();
105
+ readonly onDidRecieveKernelMessage = this.onDidReceiveKernelMessageEmitter.event;
106
+
84
107
  protected readonly renderers = new Map<CellKind, CellRenderer>();
85
108
  protected _model?: NotebookModel;
86
109
  protected _ready: Deferred<NotebookModel> = new Deferred();
@@ -102,10 +125,15 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
102
125
  this.id = NOTEBOOK_EDITOR_ID_PREFIX + this.props.uri.toString();
103
126
  this.node.tabIndex = -1;
104
127
 
128
+ this.scrollOptions = {
129
+ suppressScrollY: true
130
+ };
131
+
105
132
  this.title.closable = true;
106
133
  this.update();
107
134
 
108
135
  this.toDispose.push(this.onDidChangeModelEmitter);
136
+ this.toDispose.push(this.onDidChangeReadOnlyEmitter);
109
137
 
110
138
  this.renderers.set(CellKind.Markup, this.markdownCellRenderer);
111
139
  this.renderers.set(CellKind.Code, this.codeCellRenderer);
@@ -116,6 +144,18 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
116
144
  this._model = await this.props.notebookData;
117
145
  this.saveable.delegate = this._model;
118
146
  this.toDispose.push(this._model);
147
+ this.toDispose.push(this._model.onDidChangeReadOnly(readOnly => {
148
+ if (readOnly) {
149
+ lock(this.title);
150
+ } else {
151
+ unlock(this.title);
152
+ }
153
+ this.onDidChangeReadOnlyEmitter.fire(readOnly);
154
+ this.update();
155
+ }));
156
+ if (this._model.readOnly) {
157
+ lock(this.title);
158
+ }
119
159
  // Ensure that the model is loaded before adding the editor
120
160
  this.notebookEditorService.addNotebookEditor(this);
121
161
  this.update();
@@ -145,12 +185,14 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
145
185
 
146
186
  protected render(): ReactNode {
147
187
  if (this._model) {
148
- return <div>
188
+ return <div className='theia-notebook-main-container'>
149
189
  {this.notebookMainToolbarRenderer.render(this._model)}
150
- <NotebookCellListView renderers={this.renderers}
151
- notebookModel={this._model}
152
- toolbarRenderer={this.cellToolbarFactory}
153
- commandRegistry={this.commandRegistry} />
190
+ <PerfectScrollbar className='theia-notebook-scroll-container'>
191
+ <NotebookCellListView renderers={this.renderers}
192
+ notebookModel={this._model}
193
+ toolbarRenderer={this.cellToolbarFactory}
194
+ commandRegistry={this.commandRegistry} />
195
+ </PerfectScrollbar>
154
196
  </div>;
155
197
  } else {
156
198
  return <div></div>;
@@ -165,4 +207,24 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
165
207
  super.onAfterDetach(msg);
166
208
  this.notebookEditorService.removeNotebookEditor(this);
167
209
  }
210
+
211
+ postKernelMessage(message: unknown): void {
212
+ this.onDidPostKernelMessageEmitter.fire(message);
213
+ }
214
+
215
+ postRendererMessage(rendererId: string, message: unknown): void {
216
+ this.onPostRendererMessageEmitter.fire({ rendererId, message });
217
+ }
218
+
219
+ recieveKernelMessage(message: unknown): void {
220
+ this.onDidReceiveKernelMessageEmitter.fire(message);
221
+ }
222
+
223
+ override dispose(): void {
224
+ this.onDidChangeModelEmitter.dispose();
225
+ this.onDidPostKernelMessageEmitter.dispose();
226
+ this.onDidReceiveKernelMessageEmitter.dispose();
227
+ this.onPostRendererMessageEmitter.dispose();
228
+ super.dispose();
229
+ }
168
230
  }
@@ -30,6 +30,11 @@ export interface NotebookRendererInfo {
30
30
  readonly requiresMessaging: boolean;
31
31
  }
32
32
 
33
+ export interface NotebookPreloadInfo {
34
+ readonly type: string;
35
+ readonly entrypoint: string;
36
+ }
37
+
33
38
  @injectable()
34
39
  export class NotebookRendererRegistry {
35
40
 
@@ -39,6 +44,12 @@ export class NotebookRendererRegistry {
39
44
  return this._notebookRenderers;
40
45
  }
41
46
 
47
+ private readonly _staticNotebookPreloads: NotebookPreloadInfo[] = [];
48
+
49
+ get staticNotebookPreloads(): readonly NotebookPreloadInfo[] {
50
+ return this._staticNotebookPreloads;
51
+ }
52
+
42
53
  registerNotebookRenderer(type: NotebookRendererDescriptor, basePath: string): Disposable {
43
54
  let entrypoint;
44
55
  if (typeof type.entrypoint === 'string') {
@@ -62,5 +73,13 @@ export class NotebookRendererRegistry {
62
73
  this._notebookRenderers.splice(this._notebookRenderers.findIndex(renderer => renderer.id === type.id), 1);
63
74
  });
64
75
  }
76
+
77
+ registerStaticNotebookPreload(type: string, entrypoint: string, basePath: string): Disposable {
78
+ const staticPreload = { type, entrypoint: new Path(basePath).join(entrypoint).toString() };
79
+ this._staticNotebookPreloads.push(staticPreload);
80
+ return Disposable.create(() => {
81
+ this._staticNotebookPreloads.splice(this._staticNotebookPreloads.indexOf(staticPreload), 1);
82
+ });
83
+ }
65
84
  }
66
85
 
@@ -16,10 +16,11 @@
16
16
 
17
17
  import { Disposable } from '@theia/core';
18
18
  import { NotebookCellModel } from '../view-model/notebook-cell-model';
19
+ import { NotebookModel } from '../view-model/notebook-model';
19
20
 
20
21
  export const CellOutputWebviewFactory = Symbol('outputWebviewFactory');
21
22
 
22
- export type CellOutputWebviewFactory = (cell: NotebookCellModel) => Promise<CellOutputWebview>;
23
+ export type CellOutputWebviewFactory = (cell: NotebookCellModel, notebook: NotebookModel) => Promise<CellOutputWebview>;
23
24
 
24
25
  export interface CellOutputWebview extends Disposable {
25
26
 
@@ -67,7 +67,6 @@ export class NotebookCellContextManager implements NotebookCellContextManager, D
67
67
 
68
68
  dispose(): void {
69
69
  this.toDispose.dispose();
70
- this.currentStore?.dispose();
71
70
  this.onDidChangeContextEmitter.dispose();
72
71
  }
73
72
  }
@@ -18,7 +18,7 @@
18
18
  * Licensed under the MIT License. See License.txt in the project root for license information.
19
19
  *--------------------------------------------------------------------------------------------*/
20
20
 
21
- import { Disposable, DisposableCollection, Emitter, URI } from '@theia/core';
21
+ import { Disposable, DisposableCollection, Emitter, URI, generateUuid } from '@theia/core';
22
22
  import { inject, injectable } from '@theia/core/shared/inversify';
23
23
  import { NotebookService } from './notebook-service';
24
24
  import {
@@ -27,7 +27,6 @@ import {
27
27
  } from '../../common';
28
28
  import { CellPartialInternalMetadataEditByHandle, CellEditOperation } from '../notebook-types';
29
29
  import { NotebookModel } from '../view-model/notebook-model';
30
- import { v4 } from 'uuid';
31
30
 
32
31
  export type CellExecuteUpdate = CellExecuteOutputEdit | CellExecuteOutputItemEdit | CellExecutionStateUpdate;
33
32
 
@@ -178,7 +177,7 @@ export class CellExecution implements Disposable {
178
177
  editType: CellEditType.PartialInternalMetadata,
179
178
  handle: this.cellHandle,
180
179
  internalMetadata: {
181
- executionId: v4(),
180
+ executionId: generateUuid(),
182
181
  runStartTime: undefined,
183
182
  runEndTime: undefined,
184
183
  lastRunSuccess: undefined,
@@ -54,6 +54,11 @@ export interface NotebookKernel {
54
54
  // ID of the extension providing this kernel
55
55
  readonly extensionId: string;
56
56
 
57
+ readonly localResourceRoot: URI;
58
+ readonly preloadUris: URI[];
59
+ readonly preloadProvides: string[];
60
+
61
+ readonly handle: number;
57
62
  label: string;
58
63
  description?: string;
59
64
  detail?: string;
@@ -144,7 +149,7 @@ export class SourceCommand implements Disposable {
144
149
 
145
150
  const NOTEBOOK_KERNEL_BINDING_STORAGE_KEY = 'notebook.kernel.bindings';
146
151
  @injectable()
147
- export class NotebookKernelService implements Disposable {
152
+ export class NotebookKernelService {
148
153
 
149
154
  @inject(NotebookService)
150
155
  protected notebookService: NotebookService;
@@ -152,33 +157,34 @@ export class NotebookKernelService implements Disposable {
152
157
  @inject(StorageService)
153
158
  protected storageService: StorageService;
154
159
 
155
- private readonly kernels = new Map<string, KernelInfo>();
160
+ protected readonly kernels = new Map<string, KernelInfo>();
156
161
 
157
- private notebookBindings: { [key: string]: string } = {};
162
+ protected notebookBindings: Record<string, string> = {};
158
163
 
159
- private readonly kernelDetectionTasks = new Map<string, string[]>();
160
- private readonly onDidChangeKernelDetectionTasksEmitter = new Emitter<string>();
164
+ protected readonly kernelDetectionTasks = new Map<string, string[]>();
165
+ protected readonly onDidChangeKernelDetectionTasksEmitter = new Emitter<string>();
161
166
  readonly onDidChangeKernelDetectionTasks = this.onDidChangeKernelDetectionTasksEmitter.event;
162
167
 
163
- private readonly onDidChangeSourceActionsEmitter = new Emitter<NotebookSourceActionChangeEvent>();
164
- private readonly kernelSourceActionProviders = new Map<string, KernelSourceActionProvider[]>();
168
+ protected readonly onDidChangeSourceActionsEmitter = new Emitter<NotebookSourceActionChangeEvent>();
169
+ protected readonly kernelSourceActionProviders = new Map<string, KernelSourceActionProvider[]>();
165
170
  readonly onDidChangeSourceActions: Event<NotebookSourceActionChangeEvent> = this.onDidChangeSourceActionsEmitter.event;
166
171
 
167
- private readonly onDidAddKernelEmitter = new Emitter<NotebookKernel>();
172
+ protected readonly onDidAddKernelEmitter = new Emitter<NotebookKernel>();
168
173
  readonly onDidAddKernel: Event<NotebookKernel> = this.onDidAddKernelEmitter.event;
169
174
 
170
- private readonly onDidRemoveKernelEmitter = new Emitter<NotebookKernel>();
175
+ protected readonly onDidRemoveKernelEmitter = new Emitter<NotebookKernel>();
171
176
  readonly onDidRemoveKernel: Event<NotebookKernel> = this.onDidRemoveKernelEmitter.event;
172
177
 
173
- private readonly onDidChangeSelectedNotebookKernelBindingEmitter = new Emitter<SelectedNotebookKernelChangeEvent>();
178
+ protected readonly onDidChangeSelectedNotebookKernelBindingEmitter = new Emitter<SelectedNotebookKernelChangeEvent>();
174
179
  readonly onDidChangeSelectedKernel: Event<SelectedNotebookKernelChangeEvent> = this.onDidChangeSelectedNotebookKernelBindingEmitter.event;
175
180
 
176
- private readonly onDidChangeNotebookAffinityEmitter = new Emitter<void>();
181
+ protected readonly onDidChangeNotebookAffinityEmitter = new Emitter<void>();
177
182
  readonly onDidChangeNotebookAffinity: Event<void> = this.onDidChangeNotebookAffinityEmitter.event;
178
183
 
179
184
  @postConstruct()
180
185
  init(): void {
181
- this.storageService.getData(NOTEBOOK_KERNEL_BINDING_STORAGE_KEY).then((value: { [key: string]: string } | undefined) => {
186
+ this.notebookService.onDidAddNotebookDocument(model => this.tryAutoBindNotebook(model));
187
+ this.storageService.getData(NOTEBOOK_KERNEL_BINDING_STORAGE_KEY).then((value: Record<string, string> | undefined) => {
182
188
  if (value) {
183
189
  this.notebookBindings = value;
184
190
  }
@@ -344,13 +350,4 @@ export class NotebookKernelService implements Disposable {
344
350
  const allActions = await Promise.all(promises);
345
351
  return allActions.flat();
346
352
  }
347
-
348
- dispose(): void {
349
- this.onDidChangeKernelDetectionTasksEmitter.dispose();
350
- this.onDidChangeSourceActionsEmitter.dispose();
351
- this.onDidAddKernelEmitter.dispose();
352
- this.onDidRemoveKernelEmitter.dispose();
353
- this.onDidChangeSelectedNotebookKernelBindingEmitter.dispose();
354
- this.onDidChangeNotebookAffinityEmitter.dispose();
355
- }
356
353
  }
@@ -14,7 +14,7 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { Emitter, URI } from '@theia/core';
17
+ import { Emitter, Resource, ResourceProvider, URI } from '@theia/core';
18
18
  import { inject, injectable } from '@theia/core/shared/inversify';
19
19
  import { UriComponents } from '@theia/core/lib/common/uri';
20
20
  import { FileService } from '@theia/filesystem/lib/browser/file-service';
@@ -34,6 +34,9 @@ export class NotebookModelResolverService {
34
34
  @inject(FileService)
35
35
  protected fileService: FileService;
36
36
 
37
+ @inject(ResourceProvider)
38
+ protected resourceProvider: ResourceProvider;
39
+
37
40
  @inject(NotebookService)
38
41
  protected notebookService: NotebookService;
39
42
 
@@ -60,9 +63,9 @@ export class NotebookModelResolverService {
60
63
  throw new Error(`Missing viewType for '${resource}'`);
61
64
  }
62
65
 
63
- const notebookData = await this.resolveExistingNotebookData(resource, viewType!);
64
-
65
- const notebookModel = await this.notebookService.createNotebookModel(notebookData, viewType, resource);
66
+ const actualResource = await this.resourceProvider(resource);
67
+ const notebookData = await this.resolveExistingNotebookData(actualResource, viewType!);
68
+ const notebookModel = await this.notebookService.createNotebookModel(notebookData, viewType, actualResource);
66
69
 
67
70
  notebookModel.onDirtyChanged(() => this.onDidChangeDirtyEmitter.fire(notebookModel));
68
71
  notebookModel.onDidSaveNotebook(() => this.onDidSaveNotebookEmitter.fire(notebookModel.uri.toComponents()));
@@ -103,8 +106,8 @@ export class NotebookModelResolverService {
103
106
  return this.resolve(resource, viewType);
104
107
  }
105
108
 
106
- protected async resolveExistingNotebookData(resource: URI, viewType: string): Promise<NotebookData> {
107
- if (resource.scheme === 'untitled') {
109
+ protected async resolveExistingNotebookData(resource: Resource, viewType: string): Promise<NotebookData> {
110
+ if (resource.uri.scheme === 'untitled') {
108
111
 
109
112
  return {
110
113
  cells: [
@@ -118,10 +121,11 @@ export class NotebookModelResolverService {
118
121
  metadata: {}
119
122
  };
120
123
  } else {
121
- const file = await this.fileService.readFile(resource);
122
-
123
- const dataProvider = await this.notebookService.getNotebookDataProvider(viewType);
124
- const notebook = await dataProvider.serializer.toNotebook(file.value);
124
+ const [dataProvider, contents] = await Promise.all([
125
+ this.notebookService.getNotebookDataProvider(viewType),
126
+ this.fileService.readFile(resource.uri)
127
+ ]);
128
+ const notebook = await dataProvider.serializer.toNotebook(contents.value);
125
129
 
126
130
  return notebook;
127
131
  }
@@ -19,8 +19,9 @@
19
19
  *--------------------------------------------------------------------------------------------*/
20
20
 
21
21
  import { Emitter } from '@theia/core';
22
- import { injectable } from '@theia/core/shared/inversify';
22
+ import { inject, injectable } from '@theia/core/shared/inversify';
23
23
  import { Disposable } from '@theia/core/shared/vscode-languageserver-protocol';
24
+ import { NotebookEditorWidgetService } from './notebook-editor-widget-service';
24
25
 
25
26
  interface RendererMessage {
26
27
  editorId: string;
@@ -50,6 +51,9 @@ export class NotebookRendererMessagingService implements Disposable {
50
51
  private readonly willActivateRendererEmitter = new Emitter<string>();
51
52
  readonly onWillActivateRenderer = this.willActivateRendererEmitter.event;
52
53
 
54
+ @inject(NotebookEditorWidgetService)
55
+ private readonly editorWidgetService: NotebookEditorWidgetService;
56
+
53
57
  private readonly activations = new Map<string /* rendererId */, undefined | RendererMessage[]>();
54
58
  private readonly scopedMessaging = new Map<string /* editorId */, RendererMessaging>();
55
59
 
@@ -86,6 +90,10 @@ export class NotebookRendererMessagingService implements Disposable {
86
90
 
87
91
  const messaging: RendererMessaging = {
88
92
  postMessage: (rendererId, message) => this.postMessage(editorId, rendererId, message),
93
+ receiveMessage: async (rendererId, message) => {
94
+ this.editorWidgetService.getNotebookEditor(editorId)?.postRendererMessage(rendererId, message);
95
+ return true;
96
+ },
89
97
  dispose: () => this.scopedMessaging.delete(editorId),
90
98
  };
91
99
 
@@ -14,7 +14,7 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { Disposable, DisposableCollection, Emitter, URI } from '@theia/core';
17
+ import { Disposable, DisposableCollection, Emitter, Resource, URI } from '@theia/core';
18
18
  import { inject, injectable } from '@theia/core/shared/inversify';
19
19
  import { BinaryBuffer } from '@theia/core/lib/common/buffer';
20
20
  import { NotebookData, TransientOptions } from '../../common';
@@ -101,14 +101,14 @@ export class NotebookService implements Disposable {
101
101
  });
102
102
  }
103
103
 
104
- async createNotebookModel(data: NotebookData, viewType: string, uri: URI): Promise<NotebookModel> {
104
+ async createNotebookModel(data: NotebookData, viewType: string, resource: Resource): Promise<NotebookModel> {
105
105
  const serializer = this.notebookProviders.get(viewType)?.serializer;
106
106
  if (!serializer) {
107
107
  throw new Error('no notebook serializer for ' + viewType);
108
108
  }
109
109
 
110
- const model = this.notebookModelFactory({ data, uri, viewType, serializer });
111
- this.notebookModels.set(uri.toString(), model);
110
+ const model = this.notebookModelFactory({ data, resource, viewType, serializer });
111
+ this.notebookModels.set(resource.uri.toString(), model);
112
112
  // Resolve cell text models right after creating the notebook model
113
113
  // This ensures that all text models are available in the plugin host
114
114
  await Promise.all(model.cells.map(e => e.resolveTextModel()));
@@ -26,11 +26,14 @@
26
26
  }
27
27
 
28
28
  .theia-notebook-cell {
29
- cursor: grab;
30
29
  display: flex;
31
30
  margin: 10px 0px;
32
31
  }
33
32
 
33
+ .theia-notebook-cell.draggable {
34
+ cursor: grab;
35
+ }
36
+
34
37
  .theia-notebook-cell:hover .theia-notebook-cell-marker {
35
38
  visibility: visible;
36
39
  }
@@ -161,9 +164,20 @@
161
164
  flex-direction: column;
162
165
  }
163
166
 
167
+ .theia-notebook-main-container {
168
+ display: flex;
169
+ flex-direction: column;
170
+ height: 100%;
171
+ overflow: hidden;
172
+ }
173
+
174
+ .theia-notebook-scroll-container {
175
+ flex: 1;
176
+ overflow: hidden;
177
+ position: relative;
178
+ }
179
+
164
180
  .theia-notebook-main-toolbar {
165
- position: sticky;
166
- top: 0;
167
181
  background: var(--theia-editor-background);
168
182
  display: flex;
169
183
  flex-direction: row;
@@ -64,11 +64,13 @@ export class NotebookCellListView extends React.Component<CellListProps, Noteboo
64
64
  {this.props.notebookModel.cells
65
65
  .map((cell, index) =>
66
66
  <React.Fragment key={'cell-' + cell.handle}>
67
- <NotebookCellDivider onAddNewCell={(kind: CellKind) => this.onAddNewCell(kind, index)}
67
+ <NotebookCellDivider
68
+ isVisible={() => this.isEnabled()}
69
+ onAddNewCell={(kind: CellKind) => this.onAddNewCell(kind, index)}
68
70
  onDrop={e => this.onDrop(e, index)}
69
71
  onDragOver={e => this.onDragOver(e, cell, 'top')} />
70
72
  {this.shouldRenderDragOverIndicator(cell, 'top') && <CellDropIndicator />}
71
- <li className={'theia-notebook-cell' + (this.state.selectedCell === cell ? ' focused' : '')}
73
+ <li className={'theia-notebook-cell' + (this.state.selectedCell === cell ? ' focused' : '') + (this.isEnabled() ? ' draggable' : '')}
72
74
  onClick={() => {
73
75
  this.setState({ selectedCell: cell });
74
76
  this.props.notebookModel.setSelectedCell(cell);
@@ -89,7 +91,9 @@ export class NotebookCellListView extends React.Component<CellListProps, Noteboo
89
91
  </React.Fragment>
90
92
  )
91
93
  }
92
- <NotebookCellDivider onAddNewCell={(kind: CellKind) => this.onAddNewCell(kind, this.props.notebookModel.cells.length)}
94
+ <NotebookCellDivider
95
+ isVisible={() => this.isEnabled()}
96
+ onAddNewCell={(kind: CellKind) => this.onAddNewCell(kind, this.props.notebookModel.cells.length)}
93
97
  onDrop={e => this.onDrop(e, this.props.notebookModel.cells.length - 1)}
94
98
  onDragOver={e => this.onDragOver(e, this.props.notebookModel.cells[this.props.notebookModel.cells.length - 1], 'bottom')} />
95
99
  </ul>;
@@ -105,18 +109,33 @@ export class NotebookCellListView extends React.Component<CellListProps, Noteboo
105
109
 
106
110
  protected onDragStart(event: React.DragEvent<HTMLLIElement>, index: number): void {
107
111
  event.stopPropagation();
112
+ if (!this.isEnabled()) {
113
+ event.preventDefault();
114
+ return;
115
+ }
108
116
  event.dataTransfer.setData('text/theia-notebook-cell-index', index.toString());
109
117
  event.dataTransfer.setData('text/plain', this.props.notebookModel.cells[index].source);
110
118
  }
111
119
 
112
120
  protected onDragOver(event: React.DragEvent<HTMLLIElement>, cell: NotebookCellModel, position?: 'top' | 'bottom'): void {
121
+ if (!this.isEnabled()) {
122
+ return;
123
+ }
113
124
  event.preventDefault();
114
125
  event.stopPropagation();
115
126
  // show indicator
116
127
  this.setState({ ...this.state, dragOverIndicator: { cell, position: position ?? event.nativeEvent.offsetY < event.currentTarget.clientHeight / 2 ? 'top' : 'bottom' } });
117
128
  }
118
129
 
130
+ protected isEnabled(): boolean {
131
+ return !Boolean(this.props.notebookModel.readOnly);
132
+ }
133
+
119
134
  protected onDrop(event: React.DragEvent<HTMLLIElement>, dropElementIndex: number): void {
135
+ if (!this.isEnabled()) {
136
+ this.setState({ dragOverIndicator: undefined });
137
+ return;
138
+ }
120
139
  const index = parseInt(event.dataTransfer.getData('text/theia-notebook-cell-index'));
121
140
  const isTargetBelow = index < dropElementIndex;
122
141
  let newIdx = this.state.dragOverIndicator?.position === 'top' ? dropElementIndex : dropElementIndex + 1;
@@ -133,15 +152,18 @@ export class NotebookCellListView extends React.Component<CellListProps, Noteboo
133
152
  }
134
153
 
135
154
  protected onAddNewCell(kind: CellKind, index: number): void {
136
- this.props.commandRegistry.executeCommand(NotebookCommands.ADD_NEW_CELL_COMMAND.id,
137
- this.props.notebookModel,
138
- kind,
139
- index
140
- );
155
+ if (this.isEnabled()) {
156
+ this.props.commandRegistry.executeCommand(NotebookCommands.ADD_NEW_CELL_COMMAND.id,
157
+ this.props.notebookModel,
158
+ kind,
159
+ index
160
+ );
161
+ }
141
162
  }
142
163
 
143
164
  protected shouldRenderDragOverIndicator(cell: NotebookCellModel, position: 'top' | 'bottom'): boolean {
144
- return this.state.dragOverIndicator !== undefined &&
165
+ return this.isEnabled() &&
166
+ this.state.dragOverIndicator !== undefined &&
145
167
  this.state.dragOverIndicator.cell === cell &&
146
168
  this.state.dragOverIndicator.position === position;
147
169
  }
@@ -149,16 +171,17 @@ export class NotebookCellListView extends React.Component<CellListProps, Noteboo
149
171
  }
150
172
 
151
173
  export interface NotebookCellDividerProps {
174
+ isVisible: () => boolean;
152
175
  onAddNewCell: (type: CellKind) => void;
153
176
  onDrop: (event: React.DragEvent<HTMLLIElement>) => void;
154
177
  onDragOver: (event: React.DragEvent<HTMLLIElement>) => void;
155
178
  }
156
179
 
157
- export function NotebookCellDivider({ onAddNewCell, onDrop, onDragOver }: NotebookCellDividerProps): React.JSX.Element {
180
+ export function NotebookCellDivider({ isVisible, onAddNewCell, onDrop, onDragOver }: NotebookCellDividerProps): React.JSX.Element {
158
181
  const [hover, setHover] = React.useState(false);
159
182
 
160
183
  return <li className='theia-notebook-cell-divider' onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)} onDrop={onDrop} onDragOver={onDragOver}>
161
- {hover && <div className='theia-notebook-add-cell-buttons'>
184
+ {hover && isVisible() && <div className='theia-notebook-add-cell-buttons'>
162
185
  <button className='theia-notebook-add-cell-button' onClick={() => onAddNewCell(CellKind.Code)} title={nls.localizeByDefault('Add Code Cell')}>
163
186
  <div className={codicon('add') + ' theia-notebook-add-cell-button-icon'} />
164
187
  {nls.localizeByDefault('Code')}
@@ -29,6 +29,7 @@ export interface NotebookCellToolbarItem {
29
29
  icon?: string;
30
30
  label?: string;
31
31
  onClick: (e: React.MouseEvent) => void;
32
+ isVisible: () => boolean;
32
33
  contextKeys?: Set<string>
33
34
  }
34
35
 
@@ -87,6 +88,7 @@ export class NotebookCellToolbarFactory {
87
88
  args: [notebookModel, cell, output]
88
89
  }) :
89
90
  () => this.commandRegistry.executeCommand(menuNode.command!, notebookModel, cell, output),
91
+ isVisible: () => menuPath ? true : Boolean(this.commandRegistry.getVisibleHandler(menuNode.command!, notebookModel, cell, output)),
90
92
  contextKeys: menuNode.when ? this.contextKeyService.parseKeys(menuNode.when) : undefined
91
93
  };
92
94
  }
@@ -56,7 +56,7 @@ export class NotebookCellToolbar extends NotebookCellActionBar {
56
56
 
57
57
  override render(): React.ReactNode {
58
58
  return <div className='theia-notebook-cell-toolbar'>
59
- {this.state.inlineItems.map(item => this.renderItem(item))}
59
+ {this.state.inlineItems.filter(e => e.isVisible()).map(item => this.renderItem(item))}
60
60
  </div>;
61
61
  }
62
62
 
@@ -66,7 +66,7 @@ export class NotebookCellSidebar extends NotebookCellActionBar {
66
66
 
67
67
  override render(): React.ReactNode {
68
68
  return <div className='theia-notebook-cell-sidebar'>
69
- {this.state.inlineItems.map(item => this.renderItem(item))}
69
+ {this.state.inlineItems.filter(e => e.isVisible()).map(item => this.renderItem(item))}
70
70
  </div>;
71
71
  }
72
72
  }