Skip to content
7 changes: 7 additions & 0 deletions src/client/datascience/interactive-common/synchronization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export type IInteractiveActionMapping = MessageMapping<IInteractiveWindowMapping
// This way, if a new message is added, we'll make the decision early on whether it needs to be synchronized and how.
// Rather than waiting for users to report issues related to new messages.
const messageWithMessageTypes: MessageMapping<IInteractiveWindowMapping> & MessageMapping<CommonActionTypeMapping> = {
[CommonActionType.ADD_AND_FOCUS_NEW_CELL]: MessageType.other,
[CommonActionType.ADD_NEW_CELL]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.ARROW_DOWN]: MessageType.syncWithLiveShare,
[CommonActionType.ARROW_UP]: MessageType.syncWithLiveShare,
Expand All @@ -40,6 +41,7 @@ const messageWithMessageTypes: MessageMapping<IInteractiveWindowMapping> & Messa
[CommonActionType.COPY_CELL_CODE]: MessageType.other,
[CommonActionType.EDITOR_LOADED]: MessageType.other,
[CommonActionType.EDIT_CELL]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.EXECUTE_CELL_AND_ADVANCE]: MessageType.other,
[CommonActionType.EXECUTE_ABOVE]: MessageType.other,
[CommonActionType.EXECUTE_ALL_CELLS]: MessageType.other,
[CommonActionType.EXECUTE_CELL]: MessageType.other,
Expand All @@ -49,9 +51,12 @@ const messageWithMessageTypes: MessageMapping<IInteractiveWindowMapping> & Messa
[CommonActionType.GATHER_CELL]: MessageType.other,
[CommonActionType.GET_VARIABLE_DATA]: MessageType.other,
[CommonActionType.GOTO_CELL]: MessageType.syncWithLiveShare,
[CommonActionType.INSERT_ABOVE_AND_FOCUS_NEW_CELL]: MessageType.other,
[CommonActionType.INSERT_ABOVE]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.INSERT_ABOVE_FIRST_AND_FOCUS_NEW_CELL]: MessageType.other,
[CommonActionType.INSERT_ABOVE_FIRST]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.INSERT_BELOW]: MessageType.syncAcrossSameNotebooks | MessageType.syncWithLiveShare,
[CommonActionType.INSERT_BELOW_AND_FOCUS_NEW_CELL]: MessageType.other,
[CommonActionType.INTERRUPT_KERNEL]: MessageType.other,
[CommonActionType.LOADED_ALL_CELLS]: MessageType.other,
[CommonActionType.LINK_CLICK]: MessageType.other,
Expand All @@ -71,6 +76,8 @@ const messageWithMessageTypes: MessageMapping<IInteractiveWindowMapping> & Messa
[CommonActionType.TOGGLE_VARIABLE_EXPLORER]: MessageType.syncWithLiveShare,
[CommonActionType.UNFOCUS_CELL]: MessageType.syncWithLiveShare,
[CommonActionType.UNMOUNT]: MessageType.other,
[CommonActionType.PostOutgoingMessage]: MessageType.other,
[CommonActionType.REFRESH_VARIABLES]: MessageType.other,

// Types from InteractiveWindowMessages
[InteractiveWindowMessages.Activate]: MessageType.other,
Expand Down
3 changes: 2 additions & 1 deletion src/client/datascience/interactive-ipynb/nativeEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { inject, injectable, multiInject, named } from 'inversify';
import * as path from 'path';
import { Event, EventEmitter, Memento, Uri, ViewColumn, WebviewPanel } from 'vscode';

import * as uuid from 'uuid/v4';
import { createCodeCell, createErrorOutput } from '../../../datascience-ui/common/cellFactory';
import { IApplicationShell, ICommandManager, IDocumentManager, ILiveShareApi, IWebPanelProvider, IWorkspaceService } from '../../common/application/types';
import { ContextKey } from '../../common/contextKey';
Expand Down Expand Up @@ -239,7 +240,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
}

public addCellBelow() {
this.postMessage(InteractiveWindowMessages.NotebookAddCellBelow).ignoreErrors();
this.postMessage(InteractiveWindowMessages.NotebookAddCellBelow, { newCellId: uuid() }).ignoreErrors();
}

protected addSysInfo(_reason: SysInfoReason): Promise<void> {
Expand Down
2 changes: 1 addition & 1 deletion src/datascience-ui/history-react/redux/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const actionCreators = {
undo: (): CommonAction => createIncomingAction(InteractiveWindowMessages.Undo),
redo: (): CommonAction => createIncomingAction(InteractiveWindowMessages.Redo),
linkClick: (href: string): CommonAction<ILinkClickAction> => createIncomingActionWithPayload(CommonActionType.LINK_CLICK, { href }),
showPlot: (imageHtml: string): CommonAction<string> => createIncomingActionWithPayload(InteractiveWindowMessages.ShowPlot, imageHtml),
showPlot: (imageHtml: string) => createIncomingActionWithPayload(InteractiveWindowMessages.ShowPlot, imageHtml),
toggleInputBlock: (cellId: string): CommonAction<ICellAction> => createIncomingActionWithPayload(CommonActionType.TOGGLE_INPUT_BLOCK, { cellId }),
gotoCell: (cellId: string): CommonAction<ICellAction> => createIncomingActionWithPayload(CommonActionType.GOTO_CELL, { cellId }),
copyCellCode: (cellId: string): CommonAction<ICellAction> => createIncomingActionWithPayload(CommonActionType.COPY_CELL_CODE, { cellId }),
Expand Down
6 changes: 3 additions & 3 deletions src/datascience-ui/interactive-common/redux/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as Redux from 'redux';
import { IInteractiveWindowMapping, InteractiveWindowMessages } from '../../../client/datascience/interactive-common/interactiveWindowTypes';
import { BaseReduxActionPayload } from '../../../client/datascience/interactive-common/types';
import { CssMessages, SharedMessages } from '../../../client/datascience/messages';
import { CommonAction, CommonActionType } from './reducers/types';
import { CommonAction, CommonActionType, CommonActionTypeMapping } from './reducers/types';

const AllowedMessages = [...Object.values(InteractiveWindowMessages), ...Object.values(CssMessages), ...Object.values(SharedMessages), ...Object.values(CommonActionType)];
export function isAllowedMessage(message: string) {
Expand All @@ -18,9 +18,9 @@ export function isAllowedAction(action: Redux.AnyAction) {
return isAllowedMessage(action.type);
}

export function createIncomingActionWithPayload<T>(type: CommonActionType | InteractiveWindowMessages, data: T): CommonAction<T> {
export function createIncomingActionWithPayload<M extends IInteractiveWindowMapping & CommonActionTypeMapping, K extends keyof M>(type: K, data: M[K]): CommonAction<M[K]> {
// tslint:disable-next-line: no-any
return { type, payload: ({ data, messageDirection: 'incoming' } as any) as BaseReduxActionPayload<T> };
return { type, payload: { data, messageDirection: 'incoming' } as any } as any;
}
export function createIncomingAction(type: CommonActionType | InteractiveWindowMessages): CommonAction {
return { type, payload: { messageDirection: 'incoming', data: undefined } };
Expand Down
25 changes: 16 additions & 9 deletions src/datascience-ui/interactive-common/redux/reducers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import { CursorPos, IMainState } from '../../mainState';
*/

export enum CommonActionType {
ADD_AND_FOCUS_NEW_CELL = 'action.add_new_cell_and_focus_cell',
INSERT_ABOVE_AND_FOCUS_NEW_CELL = 'action.insert_above_and_focus_cell',
INSERT_BELOW_AND_FOCUS_NEW_CELL = 'action.insert_below_and_focus_cell',
INSERT_ABOVE_FIRST_AND_FOCUS_NEW_CELL = 'action.insert_above_first_and_focus_cell',
ADD_NEW_CELL = 'action.add_new_cell',
ARROW_DOWN = 'action.arrow_down',
ARROW_UP = 'action.arrow_up',
Expand All @@ -34,6 +38,7 @@ export enum CommonActionType {
EXECUTE_ABOVE = 'action.execute_above',
EXECUTE_ALL_CELLS = 'action.execute_all_cells',
EXECUTE_CELL = 'action.execute_cell',
EXECUTE_CELL_AND_ADVANCE = 'action.execute_cell_and_advance',
EXECUTE_CELL_AND_BELOW = 'action.execute_cell_and_below',
EXPORT = 'action.export',
FOCUS_CELL = 'action.focus_cell',
Expand Down Expand Up @@ -67,13 +72,18 @@ export enum CommonActionType {
}

export type CommonActionTypeMapping = {
[CommonActionType.ADD_AND_FOCUS_NEW_CELL]: IAddCellAction;
[CommonActionType.INSERT_ABOVE]: ICellAction & IAddCellAction;
[CommonActionType.INSERT_BELOW]: ICellAction & IAddCellAction;
[CommonActionType.INSERT_ABOVE_FIRST]: IAddCellAction;
[CommonActionType.INSERT_ABOVE_FIRST_AND_FOCUS_NEW_CELL]: IAddCellAction;
[CommonActionType.INSERT_BELOW_AND_FOCUS_NEW_CELL]: ICellAction & IAddCellAction;
[CommonActionType.INSERT_ABOVE_AND_FOCUS_NEW_CELL]: ICellAction & IAddCellAction;
[CommonActionType.FOCUS_CELL]: ICellAndCursorAction;
[CommonActionType.UNFOCUS_CELL]: ICodeAction;
[CommonActionType.UNFOCUS_CELL]: ICellAction | ICodeAction;
[CommonActionType.ADD_NEW_CELL]: IAddCellAction;
[CommonActionType.EDIT_CELL]: IEditCellAction;
[CommonActionType.EXECUTE_CELL_AND_ADVANCE]: IExecuteAction;
[CommonActionType.EXECUTE_CELL]: IExecuteAction;
[CommonActionType.EXECUTE_ALL_CELLS]: never | undefined;
[CommonActionType.EXECUTE_ABOVE]: ICellAction;
Expand Down Expand Up @@ -108,6 +118,8 @@ export type CommonActionTypeMapping = {
[CommonActionType.CODE_CREATED]: ICodeCreatedAction;
[CommonActionType.GET_VARIABLE_DATA]: IJupyterVariablesRequest;
[CommonActionType.TOGGLE_VARIABLE_EXPLORER]: never | undefined;
[CommonActionType.PostOutgoingMessage]: never | undefined;
[CommonActionType.REFRESH_VARIABLES]: never | undefined;
};

export interface IShowDataViewerAction extends IShowDataViewer {}
Expand Down Expand Up @@ -149,14 +161,9 @@ export interface IEditCellAction extends ICodeAction {

// I.e. when using the operation `add`, we need the corresponding `IAddCellAction`.
// They are mutually exclusive, if not `add`, then there's no `newCellId`.
export type IExecuteAction =
| (ICodeAction & {
moveOp: 'select' | 'none';
})
| (ICodeAction &
IAddCellAction & {
moveOp: 'add';
});
export type IExecuteAction = ICodeAction & {
moveOp: 'select' | 'none' | 'add';
};

export interface ICodeCreatedAction extends ICellAction {
modelId: string;
Expand Down
3 changes: 3 additions & 0 deletions src/datascience-ui/interactive-common/redux/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ function createTestMiddleware(): Redux.Middleware<{}, IStore> {
sendMessage(InteractiveWindowMessages.ExecutionRendered, { ids: diff });
}

if (action.type !== 'action.postOutgoingMessage') {
sendMessage(`DISPATCHED_ACTION_${action.type}`, {});
}
return res;
};
}
Expand Down
11 changes: 7 additions & 4 deletions src/datascience-ui/native-editor/nativeCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -271,13 +271,15 @@ export class NativeCell extends React.Component<INativeCellProps> {
case 'l':
if (!this.isFocused() && this.isSelected()) {
e.stopPropagation();
e.preventDefault();
this.props.toggleLineNumbers(cellId);
this.props.sendCommand(NativeCommandType.ToggleLineNumbers, 'keyboard');
}
break;
case 'o':
if (!this.isFocused() && this.isSelected()) {
e.stopPropagation();
e.preventDefault();
this.props.toggleOutput(cellId);
this.props.sendCommand(NativeCommandType.ToggleOutput, 'keyboard');
}
Expand Down Expand Up @@ -305,18 +307,19 @@ export class NativeCell extends React.Component<INativeCellProps> {
case 'a':
if (!this.isFocused()) {
e.stopPropagation();
this.props.insertAbove(cellId);
e.preventDefault();
setTimeout(() => this.props.insertAbove(cellId), 1);
this.props.sendCommand(NativeCommandType.InsertAbove, 'keyboard');
}
break;
case 'b':
if (!this.isFocused()) {
e.stopPropagation();
this.props.insertBelow(cellId);
e.preventDefault();
setTimeout(() => this.props.insertBelow(cellId), 1);
this.props.sendCommand(NativeCommandType.InsertBelow, 'keyboard');
}
break;

default:
break;
}
Expand Down Expand Up @@ -420,7 +423,7 @@ export class NativeCell extends React.Component<INativeCellProps> {
};

private addNewCell = () => {
this.props.insertBelow(this.cellId);
setTimeout(() => this.props.insertBelow(this.cellId), 1);
this.props.sendCommand(NativeCommandType.AddToEnd, 'mouse');
};

Expand Down
10 changes: 7 additions & 3 deletions src/datascience-ui/native-editor/nativeEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export class NativeEditor extends React.Component<INativeEditorProps> {

constructor(props: INativeEditorProps) {
super(props);
this.insertAboveFirst = this.insertAboveFirst.bind(this);
}

public componentDidMount() {
Expand Down Expand Up @@ -83,7 +84,7 @@ export class NativeEditor extends React.Component<INativeEditorProps> {
const progressBar = this.props.busy && !this.props.testMode ? <Progress /> : undefined;
const addCellLine =
this.props.cellVMs.length === 0 ? null : (
<AddCellLine includePlus={true} className="add-cell-line-top" click={this.props.insertAboveFirst} baseTheme={this.props.baseTheme} />
<AddCellLine includePlus={true} className="add-cell-line-top" click={this.insertAboveFirst} baseTheme={this.props.baseTheme} />
);

return (
Expand All @@ -106,13 +107,16 @@ export class NativeEditor extends React.Component<INativeEditorProps> {
);
}

private insertAboveFirst() {
setTimeout(() => this.props.insertAboveFirst(), 1);
}
// tslint:disable: react-this-binding-issue
// tslint:disable-next-line: max-func-body-length
private renderToolbarPanel() {
const selectedInfo = getSelectedAndFocusedInfo(this.props);

const addCell = () => {
this.props.addCell();
setTimeout(() => this.props.addCell(), 1);
this.props.sendCommand(NativeCommandType.AddToEnd, 'mouse');
};
const runAll = () => {
Expand Down Expand Up @@ -357,7 +361,7 @@ export class NativeEditor extends React.Component<INativeEditorProps> {
}

const addNewCell = () => {
this.props.insertBelow(cellVM.cell.id);
setTimeout(() => this.props.insertBelow(cellVM.cell.id), 1);
this.props.sendCommand(NativeCommandType.AddToEnd, 'mouse');
};
const firstLine = index === 0;
Expand Down
29 changes: 9 additions & 20 deletions src/datascience-ui/native-editor/redux/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,11 @@ import { createIncomingAction, createIncomingActionWithPayload } from '../../int
import {
CommonAction,
CommonActionType,
IAddCellAction,
ICellAction,
ICellAndCursorAction,
IChangeCellTypeAction,
ICodeAction,
ICodeCreatedAction,
IEditCellAction,
IExecuteAction,
ILinkClickAction,
ISendCommandAction,
IShowDataViewerAction
Expand All @@ -25,24 +22,17 @@ import { IMonacoModelContentChangeEvent } from '../../react-common/monacoHelpers

// See https://react-redux.js.org/using-react-redux/connect-mapdispatch#defining-mapdispatchtoprops-as-an-object
export const actionCreators = {
insertAbove: (cellId: string | undefined): CommonAction<ICellAction & IAddCellAction> =>
createIncomingActionWithPayload(CommonActionType.INSERT_ABOVE, { cellId, newCellId: uuid() }),
insertAboveFirst: (): CommonAction<IAddCellAction> => createIncomingActionWithPayload(CommonActionType.INSERT_ABOVE_FIRST, { newCellId: uuid() }),
insertBelow: (cellId: string | undefined): CommonAction<ICellAction & IAddCellAction> =>
createIncomingActionWithPayload(CommonActionType.INSERT_BELOW, { cellId, newCellId: uuid() }),
addCell: () => createIncomingActionWithPayload(CommonActionType.ADD_AND_FOCUS_NEW_CELL, { newCellId: uuid() }),
insertAboveFirst: () => createIncomingActionWithPayload(CommonActionType.INSERT_ABOVE_FIRST_AND_FOCUS_NEW_CELL, { newCellId: uuid() }),
insertAbove: (cellId: string | undefined) => createIncomingActionWithPayload(CommonActionType.INSERT_ABOVE_AND_FOCUS_NEW_CELL, { cellId, newCellId: uuid() }),
insertBelow: (cellId: string | undefined) => createIncomingActionWithPayload(CommonActionType.INSERT_BELOW_AND_FOCUS_NEW_CELL, { cellId, newCellId: uuid() }),
executeCell: (cellId: string, code: string, moveOp: 'add' | 'select' | 'none') =>
createIncomingActionWithPayload(CommonActionType.EXECUTE_CELL_AND_ADVANCE, { cellId, code, moveOp }),
focusCell: (cellId: string, cursorPos: CursorPos = CursorPos.Current): CommonAction<ICellAndCursorAction> =>
createIncomingActionWithPayload(CommonActionType.FOCUS_CELL, { cellId, cursorPos }),
unfocusCell: (cellId: string, code: string): CommonAction<ICodeAction> => createIncomingActionWithPayload(CommonActionType.UNFOCUS_CELL, { cellId, code }),
unfocusCell: (cellId: string, code: string) => createIncomingActionWithPayload(CommonActionType.UNFOCUS_CELL, { cellId, code }),
selectCell: (cellId: string, cursorPos: CursorPos = CursorPos.Current): CommonAction<ICellAndCursorAction> =>
createIncomingActionWithPayload(CommonActionType.SELECT_CELL, { cellId, cursorPos }),
addCell: (): CommonAction<IAddCellAction> => createIncomingActionWithPayload(CommonActionType.ADD_NEW_CELL, { newCellId: uuid() }),
executeCell: (cellId: string, code: string, moveOp: 'add' | 'select' | 'none'): CommonAction<IExecuteAction> => {
if (moveOp === 'add') {
return createIncomingActionWithPayload(CommonActionType.EXECUTE_CELL, { cellId, code, moveOp, newCellId: uuid() });
} else {
return createIncomingActionWithPayload(CommonActionType.EXECUTE_CELL, { cellId, code, moveOp });
}
},
executeAllCells: (): CommonAction => createIncomingAction(CommonActionType.EXECUTE_ALL_CELLS),
executeAbove: (cellId: string): CommonAction<ICellAction> => createIncomingActionWithPayload(CommonActionType.EXECUTE_ABOVE, { cellId }),
executeCellAndBelow: (cellId: string, code: string): CommonAction<ICodeAction> => createIncomingActionWithPayload(CommonActionType.EXECUTE_CELL_AND_BELOW, { cellId, code }),
Expand All @@ -58,8 +48,7 @@ export const actionCreators = {
createIncomingActionWithPayload(CommonActionType.SEND_COMMAND, { command, commandType }),
moveCellUp: (cellId: string): CommonAction<ICellAction> => createIncomingActionWithPayload(CommonActionType.MOVE_CELL_UP, { cellId }),
moveCellDown: (cellId: string): CommonAction<ICellAction> => createIncomingActionWithPayload(CommonActionType.MOVE_CELL_DOWN, { cellId }),
changeCellType: (cellId: string, currentCode: string): CommonAction<IChangeCellTypeAction> =>
createIncomingActionWithPayload(CommonActionType.CHANGE_CELL_TYPE, { cellId, currentCode }),
changeCellType: (cellId: string, currentCode: string) => createIncomingActionWithPayload(CommonActionType.CHANGE_CELL_TYPE, { cellId, currentCode }),
toggleLineNumbers: (cellId: string): CommonAction<ICellAction> => createIncomingActionWithPayload(CommonActionType.TOGGLE_LINE_NUMBERS, { cellId }),
toggleOutput: (cellId: string): CommonAction<ICellAction> => createIncomingActionWithPayload(CommonActionType.TOGGLE_OUTPUT, { cellId }),
deleteCell: (cellId: string): CommonAction<ICellAction> => createIncomingActionWithPayload(CommonActionType.DELETE_CELL, { cellId }),
Expand All @@ -78,7 +67,7 @@ export const actionCreators = {
code: e.model.getValue()
}),
linkClick: (href: string): CommonAction<ILinkClickAction> => createIncomingActionWithPayload(CommonActionType.LINK_CLICK, { href }),
showPlot: (imageHtml: string): CommonAction<string> => createIncomingActionWithPayload(InteractiveWindowMessages.ShowPlot, imageHtml),
showPlot: (imageHtml: string) => createIncomingActionWithPayload(InteractiveWindowMessages.ShowPlot, imageHtml),
gatherCell: (cellId: string | undefined): CommonAction<ICellAction> => createIncomingActionWithPayload(CommonActionType.GATHER_CELL, { cellId }),
editorLoaded: (): CommonAction => createIncomingAction(CommonActionType.EDITOR_LOADED),
codeCreated: (cellId: string | undefined, modelId: string): CommonAction<ICodeCreatedAction> =>
Expand Down
Loading