Skip to content

Commit 94317e3

Browse files
committed
Show cell run progress for a minimum of 200ms
1 parent cf1b357 commit 94317e3

File tree

2 files changed

+58
-33
lines changed

2 files changed

+58
-33
lines changed

src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { Range } from 'vs/editor/common/core/range';
1919
import { FindMatch, IReadonlyTextBuffer, ITextModel } from 'vs/editor/common/model';
2020
import { ContextKeyExpr, RawContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
2121
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer';
22-
import { CellLanguageStatusBarItem, TimerRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer';
22+
import { CellLanguageStatusBarItem, RunStateRenderer, TimerRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer';
2323
import { CellViewModel, IModelDecorationsChangeAccessor, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
2424
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
2525
import { CellKind, IProcessedOutput, IRenderOutput, NotebookCellMetadata, NotebookDocumentMetadata, INotebookKernelInfo, IEditor, INotebookKernelInfo2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
@@ -489,7 +489,7 @@ export interface MarkdownCellRenderTemplate extends BaseCellRenderTemplate {
489489
}
490490

491491
export interface CodeCellRenderTemplate extends BaseCellRenderTemplate {
492-
cellRunStatusContainer: HTMLElement;
492+
cellRunState: RunStateRenderer;
493493
cellStatusMessageContainer: HTMLElement;
494494
runToolbar: ToolBar;
495495
runButtonContainer: HTMLElement;

src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
964964

965965
const statusBar = this.instantiationService.createInstance(CellEditorStatusBar, editorPart);
966966
const timer = new TimerRenderer(statusBar.durationContainer);
967+
const cellRunState = new RunStateRenderer(statusBar.cellRunStatusContainer, runToolbar, this.instantiationService);
967968

968969
const outputContainer = DOM.append(container, $('.output'));
969970

@@ -986,7 +987,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
986987
container,
987988
cellContainer,
988989
statusBarContainer: statusBar.statusBarContainer,
989-
cellRunStatusContainer: statusBar.cellRunStatusContainer,
990+
cellRunState,
990991
cellStatusMessageContainer: statusBar.cellStatusMessageContainer,
991992
languageStatusBarItem: statusBar.languageStatusBarItem,
992993
progressBar,
@@ -1022,26 +1023,6 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
10221023
return templateData;
10231024
}
10241025

1025-
private updateForRunState(runState: NotebookCellRunState | undefined, templateData: CodeCellRenderTemplate): void {
1026-
if (typeof runState === 'undefined') {
1027-
runState = NotebookCellRunState.Idle;
1028-
}
1029-
1030-
if (runState === NotebookCellRunState.Running) {
1031-
templateData.progressBar.infinite().show(500);
1032-
1033-
templateData.runToolbar.setActions([
1034-
this.instantiationService.createInstance(CancelCellAction)
1035-
]);
1036-
} else {
1037-
templateData.progressBar.hide();
1038-
1039-
templateData.runToolbar.setActions([
1040-
this.instantiationService.createInstance(ExecuteCellAction)
1041-
]);
1042-
}
1043-
}
1044-
10451026
private updateForOutputs(element: CodeCellViewModel, templateData: CodeCellRenderTemplate): void {
10461027
if (element.outputs.length) {
10471028
DOM.show(templateData.focusSinkElement);
@@ -1056,15 +1037,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
10561037
this.updateExecutionOrder(metadata, templateData);
10571038
templateData.cellStatusMessageContainer.textContent = metadata?.statusMessage || '';
10581039

1059-
if (metadata.runState === NotebookCellRunState.Success) {
1060-
templateData.cellRunStatusContainer.innerHTML = renderCodicons('$(check)');
1061-
} else if (metadata.runState === NotebookCellRunState.Error) {
1062-
templateData.cellRunStatusContainer.innerHTML = renderCodicons('$(error)');
1063-
} else if (metadata.runState === NotebookCellRunState.Running) {
1064-
templateData.cellRunStatusContainer.innerHTML = renderCodicons('$(sync~spin)');
1065-
} else {
1066-
templateData.cellRunStatusContainer.innerHTML = '';
1067-
}
1040+
templateData.cellRunState.renderState(element.metadata?.runState);
10681041

10691042
if (metadata.runState === NotebookCellRunState.Running) {
10701043
if (metadata.runStartTime) {
@@ -1082,7 +1055,11 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
10821055
this.editorOptions.setGlyphMargin(metadata.breakpointMargin);
10831056
}
10841057

1085-
this.updateForRunState(metadata.runState, templateData);
1058+
if (metadata.runState === NotebookCellRunState.Running) {
1059+
templateData.progressBar.infinite().show(500);
1060+
} else {
1061+
templateData.progressBar.hide();
1062+
}
10861063
}
10871064

10881065
private updateExecutionOrder(metadata: NotebookCellMetadata, templateData: CodeCellRenderTemplate): void {
@@ -1141,6 +1118,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
11411118
this.updateForLayout(element, templateData);
11421119
}));
11431120

1121+
templateData.cellRunState.clear();
11441122
this.updateForMetadata(element, templateData);
11451123
this.updateForHover(element, templateData);
11461124
elementDisposables.add(element.onDidChangeState((e) => {
@@ -1230,3 +1208,50 @@ export class TimerRenderer {
12301208
return `${seconds}.${tenths}s`;
12311209
}
12321210
}
1211+
1212+
export class RunStateRenderer {
1213+
private static readonly MIN_SPINNER_TIME = 200;
1214+
1215+
private spinnerTimer: NodeJS.Timeout | undefined;
1216+
private pendingNewState: NotebookCellRunState | undefined;
1217+
1218+
constructor(private readonly element: HTMLElement, private readonly runToolbar: ToolBar, private readonly instantiationService: IInstantiationService) {
1219+
}
1220+
1221+
clear() {
1222+
if (this.spinnerTimer) {
1223+
clearTimeout(this.spinnerTimer);
1224+
}
1225+
}
1226+
1227+
renderState(runState: NotebookCellRunState = NotebookCellRunState.Idle) {
1228+
if (this.spinnerTimer) {
1229+
this.pendingNewState = runState;
1230+
return;
1231+
}
1232+
1233+
if (runState === NotebookCellRunState.Running) {
1234+
this.runToolbar.setActions([this.instantiationService.createInstance(CancelCellAction)]);
1235+
} else {
1236+
this.runToolbar.setActions([this.instantiationService.createInstance(ExecuteCellAction)]);
1237+
}
1238+
1239+
if (runState === NotebookCellRunState.Success) {
1240+
this.element.innerHTML = renderCodicons('$(check)');
1241+
} else if (runState === NotebookCellRunState.Error) {
1242+
this.element.innerHTML = renderCodicons('$(error)');
1243+
} else if (runState === NotebookCellRunState.Running) {
1244+
this.element.innerHTML = renderCodicons('$(sync~spin)');
1245+
1246+
this.spinnerTimer = setTimeout(() => {
1247+
this.spinnerTimer = undefined;
1248+
if (this.pendingNewState) {
1249+
this.renderState(this.pendingNewState);
1250+
this.pendingNewState = undefined;
1251+
}
1252+
}, RunStateRenderer.MIN_SPINNER_TIME);
1253+
} else {
1254+
this.element.innerHTML = '';
1255+
}
1256+
}
1257+
}

0 commit comments

Comments
 (0)