From c2cd9cc29eb51246d74eadbc5a7d7c5aee582055 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 3 Feb 2020 11:50:35 -0800 Subject: [PATCH 1/9] Disable noisy logging --- src/datascience-ui/interactive-common/redux/store.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/datascience-ui/interactive-common/redux/store.ts b/src/datascience-ui/interactive-common/redux/store.ts index c547d81437a3..7d4b372ffb06 100644 --- a/src/datascience-ui/interactive-common/redux/store.ts +++ b/src/datascience-ui/interactive-common/redux/store.ts @@ -201,17 +201,18 @@ function createMiddleWare(testMode: boolean): Redux.Middleware<{}, IStore>[] { return action; } }); - const loggerMiddleware = process.env.VSC_PYTHON_FORCE_LOGGING !== undefined || (process.env.NODE_ENV !== 'production' && !testMode) ? logger : undefined; + // const loggerMiddleware = process.env.VSC_PYTHON_FORCE_LOGGING !== undefined || (process.env.NODE_ENV !== 'production' && !testMode) ? logger : undefined; // tslint:disable-next-line: no-console + console.log(logger); const results: Redux.Middleware<{}, IStore>[] = []; results.push(queueableActions); results.push(updateContext); if (testMiddleware) { results.push(testMiddleware); } - if (loggerMiddleware) { - results.push(loggerMiddleware); - } + // if (loggerMiddleware) { + // results.push(loggerMiddleware); + // } return results; } From ffc40bad136b30f8cc8bfa99c83b1173bc9c335e Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 3 Feb 2020 12:18:23 -0800 Subject: [PATCH 2/9] Restore changes --- src/datascience-ui/interactive-common/redux/store.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/datascience-ui/interactive-common/redux/store.ts b/src/datascience-ui/interactive-common/redux/store.ts index 7d4b372ffb06..c547d81437a3 100644 --- a/src/datascience-ui/interactive-common/redux/store.ts +++ b/src/datascience-ui/interactive-common/redux/store.ts @@ -201,18 +201,17 @@ function createMiddleWare(testMode: boolean): Redux.Middleware<{}, IStore>[] { return action; } }); - // const loggerMiddleware = process.env.VSC_PYTHON_FORCE_LOGGING !== undefined || (process.env.NODE_ENV !== 'production' && !testMode) ? logger : undefined; + const loggerMiddleware = process.env.VSC_PYTHON_FORCE_LOGGING !== undefined || (process.env.NODE_ENV !== 'production' && !testMode) ? logger : undefined; // tslint:disable-next-line: no-console - console.log(logger); const results: Redux.Middleware<{}, IStore>[] = []; results.push(queueableActions); results.push(updateContext); if (testMiddleware) { results.push(testMiddleware); } - // if (loggerMiddleware) { - // results.push(loggerMiddleware); - // } + if (loggerMiddleware) { + results.push(loggerMiddleware); + } return results; } From a79b03287478b10287a7c0ca80e55814ae626f2b Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 30 Jan 2020 15:43:46 -0800 Subject: [PATCH 3/9] Ensure we have a base type for all action payloads --- .../datascience/interactive-common/types.ts | 18 +++++ .../history-react/redux/mapping.ts | 60 ++++++++++------- .../history-react/redux/reducers/effects.ts | 2 +- .../redux/reducers/commonEffects.ts | 2 +- .../redux/reducers/monaco.ts | 25 ++++--- .../redux/reducers/types.ts | 10 ++- .../redux/reducers/variables.ts | 19 ++++-- .../native-editor/redux/actions.ts | 4 +- .../native-editor/redux/mapping.ts | 66 +++++++++++-------- .../native-editor/redux/reducers/effects.ts | 2 +- src/datascience-ui/react-common/reduxUtils.ts | 12 +++- 11 files changed, 145 insertions(+), 75 deletions(-) create mode 100644 src/client/datascience/interactive-common/types.ts diff --git a/src/client/datascience/interactive-common/types.ts b/src/client/datascience/interactive-common/types.ts new file mode 100644 index 000000000000..3119b447cda7 --- /dev/null +++ b/src/client/datascience/interactive-common/types.ts @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +'use strict'; + +// Stuff common to React and Extensions. + +// This forms the base content of every payload in all dispatchers. +export type BaseReduxActionPayload = { + /** + * If this property exists, then this is an action that has been dispatched for the solve purpose of: + * 1. Synchronizing states across different editors (pointing to the same file). + * 2. Synchronizing states across different editors (pointing to the same file) in different sessions. + * + * @type {('syncEditors' | 'syncSessions')} + */ + broadcastReason?: 'syncEditors' | 'syncSessions'; +}; diff --git a/src/datascience-ui/history-react/redux/mapping.ts b/src/datascience-ui/history-react/redux/mapping.ts index 3375ae0cd0a7..a169b127268c 100644 --- a/src/datascience-ui/history-react/redux/mapping.ts +++ b/src/datascience-ui/history-react/redux/mapping.ts @@ -2,6 +2,7 @@ // Licensed under the MIT License. 'use strict'; import { IScrollToCell } from '../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { BaseReduxActionPayload } from '../../../client/datascience/interactive-common/types'; import { IGetCssResponse } from '../../../client/datascience/messages'; import { IGetMonacoThemeResponse } from '../../../client/datascience/monacoMessages'; import { ICell } from '../../../client/datascience/types'; @@ -16,23 +17,32 @@ import { ILinkClickAction, IScrollAction, IShowDataViewerAction, - IShowPlotAction + IShowPlotAction, + PrimitiveTypeInReduxActionPayload } from '../../interactive-common/redux/reducers/types'; import { ReducerArg, ReducerFunc } from '../../react-common/reduxUtils'; -type InteractiveReducerFunc = ReducerFunc; +type InteractiveReducerFunc = T extends never | undefined + ? ReducerFunc + : T extends PrimitiveTypeInReduxActionPayload + ? ReducerFunc + : ReducerFunc; -export type InteractiveReducerArg = ReducerArg; +export type InteractiveReducerArg = T extends never | undefined + ? ReducerArg + : T extends PrimitiveTypeInReduxActionPayload + ? ReducerArg + : ReducerArg; export class IInteractiveActionMapping { - public [CommonActionType.RESTART_KERNEL]: InteractiveReducerFunc; - public [CommonActionType.SELECT_KERNEL]: InteractiveReducerFunc; - public [CommonActionType.SELECT_SERVER]: InteractiveReducerFunc; - public [CommonActionType.INTERRUPT_KERNEL]: InteractiveReducerFunc; - public [CommonActionType.EXPORT]: InteractiveReducerFunc; - public [CommonActionType.SAVE]: InteractiveReducerFunc; - public [CommonActionType.UNDO]: InteractiveReducerFunc; - public [CommonActionType.REDO]: InteractiveReducerFunc; + public [CommonActionType.RESTART_KERNEL]: InteractiveReducerFunc; + public [CommonActionType.SELECT_KERNEL]: InteractiveReducerFunc; + public [CommonActionType.SELECT_SERVER]: InteractiveReducerFunc; + public [CommonActionType.INTERRUPT_KERNEL]: InteractiveReducerFunc; + public [CommonActionType.EXPORT]: InteractiveReducerFunc; + public [CommonActionType.SAVE]: InteractiveReducerFunc; + public [CommonActionType.UNDO]: InteractiveReducerFunc; + public [CommonActionType.REDO]: InteractiveReducerFunc; public [CommonActionType.SHOW_DATA_VIEWER]: InteractiveReducerFunc; public [CommonActionType.DELETE_CELL]: InteractiveReducerFunc; public [CommonActionType.LINK_CLICK]: InteractiveReducerFunc; @@ -44,32 +54,32 @@ export class IInteractiveActionMapping { public [CommonActionType.EDIT_CELL]: InteractiveReducerFunc; public [CommonActionType.SUBMIT_INPUT]: InteractiveReducerFunc; public [CommonActionType.DELETE_ALL_CELLS]: InteractiveReducerFunc; - public [CommonActionType.EXPAND_ALL]: InteractiveReducerFunc; - public [CommonActionType.COLLAPSE_ALL]: InteractiveReducerFunc; - public [CommonActionType.EDITOR_LOADED]: InteractiveReducerFunc; + public [CommonActionType.EXPAND_ALL]: InteractiveReducerFunc; + public [CommonActionType.COLLAPSE_ALL]: InteractiveReducerFunc; + public [CommonActionType.EDITOR_LOADED]: InteractiveReducerFunc; public [CommonActionType.SCROLL]: InteractiveReducerFunc; public [CommonActionType.CLICK_CELL]: InteractiveReducerFunc; public [CommonActionType.UNFOCUS_CELL]: InteractiveReducerFunc; - public [CommonActionType.UNMOUNT]: InteractiveReducerFunc; + public [CommonActionType.UNMOUNT]: InteractiveReducerFunc; // Messages from the extension public [IncomingMessageActions.STARTCELL]: InteractiveReducerFunc; public [IncomingMessageActions.FINISHCELL]: InteractiveReducerFunc; public [IncomingMessageActions.UPDATECELL]: InteractiveReducerFunc; - public [IncomingMessageActions.ACTIVATE]: InteractiveReducerFunc; - public [IncomingMessageActions.RESTARTKERNEL]: InteractiveReducerFunc; + public [IncomingMessageActions.ACTIVATE]: InteractiveReducerFunc; + public [IncomingMessageActions.RESTARTKERNEL]: InteractiveReducerFunc; public [IncomingMessageActions.GETCSSRESPONSE]: InteractiveReducerFunc; - public [IncomingMessageActions.MONACOREADY]: InteractiveReducerFunc; + public [IncomingMessageActions.MONACOREADY]: InteractiveReducerFunc; public [IncomingMessageActions.GETMONACOTHEMERESPONSE]: InteractiveReducerFunc; - public [IncomingMessageActions.GETALLCELLS]: InteractiveReducerFunc; - public [IncomingMessageActions.EXPANDALL]: InteractiveReducerFunc; - public [IncomingMessageActions.COLLAPSEALL]: InteractiveReducerFunc; + public [IncomingMessageActions.GETALLCELLS]: InteractiveReducerFunc; + public [IncomingMessageActions.EXPANDALL]: InteractiveReducerFunc; + public [IncomingMessageActions.COLLAPSEALL]: InteractiveReducerFunc; public [IncomingMessageActions.DELETEALLCELLS]: InteractiveReducerFunc; - public [IncomingMessageActions.STARTPROGRESS]: InteractiveReducerFunc; - public [IncomingMessageActions.STOPPROGRESS]: InteractiveReducerFunc; + public [IncomingMessageActions.STARTPROGRESS]: InteractiveReducerFunc; + public [IncomingMessageActions.STOPPROGRESS]: InteractiveReducerFunc; public [IncomingMessageActions.UPDATESETTINGS]: InteractiveReducerFunc; - public [IncomingMessageActions.STARTDEBUGGING]: InteractiveReducerFunc; - public [IncomingMessageActions.STOPDEBUGGING]: InteractiveReducerFunc; + public [IncomingMessageActions.STARTDEBUGGING]: InteractiveReducerFunc; + public [IncomingMessageActions.STOPDEBUGGING]: InteractiveReducerFunc; public [IncomingMessageActions.SCROLLTOCELL]: InteractiveReducerFunc; public [IncomingMessageActions.UPDATEKERNEL]: InteractiveReducerFunc; public [IncomingMessageActions.LOCINIT]: InteractiveReducerFunc; diff --git a/src/datascience-ui/history-react/redux/reducers/effects.ts b/src/datascience-ui/history-react/redux/reducers/effects.ts index 9c8e56064bd1..288947c00065 100644 --- a/src/datascience-ui/history-react/redux/reducers/effects.ts +++ b/src/datascience-ui/history-react/redux/reducers/effects.ts @@ -52,7 +52,7 @@ export namespace Effects { export function updateSettings(arg: InteractiveReducerArg): IMainState { // String arg should be the IDataScienceExtraSettings - const newSettingsJSON = JSON.parse(arg.payload); + const newSettingsJSON = JSON.parse(arg.payload.data); const newSettings = newSettingsJSON; const newEditorOptions = computeEditorOptions(newSettings); const newFontFamily = newSettings.extraSettings ? newSettings.extraSettings.fontFamily : arg.prevState.font.family; diff --git a/src/datascience-ui/interactive-common/redux/reducers/commonEffects.ts b/src/datascience-ui/interactive-common/redux/reducers/commonEffects.ts index 33e3133f116f..2cff42b522a3 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/commonEffects.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/commonEffects.ts @@ -47,7 +47,7 @@ export namespace CommonEffects { export function handleLocInit(arg: CommonReducerArg): IMainState { // Read in the loc strings - const locJSON = JSON.parse(arg.payload); + const locJSON = JSON.parse(arg.payload.data); storeLocStrings(locJSON); return arg.prevState; } diff --git a/src/datascience-ui/interactive-common/redux/reducers/monaco.ts b/src/datascience-ui/interactive-common/redux/reducers/monaco.ts index f3d2bbcf874a..e3c9b60e41c2 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/monaco.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/monaco.ts @@ -12,6 +12,7 @@ import { IProvideSignatureHelpResponse, IResolveCompletionItemResponse } from '../../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { BaseReduxActionPayload } from '../../../../client/datascience/interactive-common/types'; import { IGetMonacoThemeResponse } from '../../../../client/datascience/monacoMessages'; import { logMessage } from '../../../react-common/logger'; import { PostOffice } from '../../../react-common/postOffice'; @@ -19,7 +20,7 @@ import { combineReducers, QueuableAction, ReducerArg, ReducerFunc } from '../../ import { IntellisenseProvider } from '../../intellisenseProvider'; import { initializeTokenizer, registerMonacoLanguage } from '../../tokenizer'; import { IncomingMessageActions } from '../postOffice'; -import { CommonActionType, ICodeCreatedAction, IEditCellAction } from './types'; +import { CommonActionType, ICodeCreatedAction, IEditCellAction, PrimitiveTypeInReduxActionPayload } from './types'; export interface IMonacoState { onigasmData: ArrayBuffer | undefined; @@ -29,9 +30,17 @@ export interface IMonacoState { postOffice: PostOffice; } -type MonacoReducerFunc = ReducerFunc; +type MonacoReducerFunc = T extends never | undefined + ? ReducerFunc + : T extends PrimitiveTypeInReduxActionPayload + ? ReducerFunc + : ReducerFunc; -type MonacoReducerArg = ReducerArg; +type MonacoReducerArg = T extends never | undefined + ? ReducerArg + : T extends PrimitiveTypeInReduxActionPayload + ? ReducerArg + : ReducerArg; function handleStarted(arg: MonacoReducerArg): IMonacoState { // If in test mode, register the monaco provider @@ -68,7 +77,7 @@ function finishTokenizer(buffer: ArrayBuffer, tmJson: string, arg: MonacoRedu function handleLoadOnigasmResponse(arg: MonacoReducerArg): IMonacoState { // Have to convert the buffer into an ArrayBuffer for the tokenizer to load it. // tslint:disable-next-line: no-any - const typedArray = new Uint8Array((arg.payload as any).data); + const typedArray = new Uint8Array((arg.payload.data as any).data); if (arg.prevState.tmLanguageData && !arg.prevState.onigasmData && typedArray.length > 0) { // Monaco is ready. Initialize the tokenizer @@ -85,12 +94,12 @@ function handleLoadOnigasmResponse(arg: MonacoReducerArg): IMonacoState function handleLoadTmLanguageResponse(arg: MonacoReducerArg): IMonacoState { if (arg.prevState.onigasmData && !arg.prevState.tmLanguageData) { // Monaco is ready. Initialize the tokenizer - finishTokenizer(arg.prevState.onigasmData, arg.payload, arg); + finishTokenizer(arg.prevState.onigasmData, arg.payload.data, arg); } return { ...arg.prevState, - tmLanguageData: arg.payload + tmLanguageData: arg.payload.data }; } @@ -154,7 +163,7 @@ function handleUnmount(arg: MonacoReducerArg): IMonacoState { // Create a mapping between message and reducer type class IMonacoActionMapping { - public [InteractiveWindowMessages.Started]: MonacoReducerFunc; + public [InteractiveWindowMessages.Started]: MonacoReducerFunc; public [IncomingMessageActions.LOADONIGASMASSEMBLYRESPONSE]: MonacoReducerFunc; public [IncomingMessageActions.LOADTMLANGUAGERESPONSE]: MonacoReducerFunc; public [IncomingMessageActions.GETMONACOTHEMERESPONSE]: MonacoReducerFunc; @@ -164,7 +173,7 @@ class IMonacoActionMapping { public [IncomingMessageActions.RESOLVECOMPLETIONITEMRESPONSE]: MonacoReducerFunc; public [CommonActionType.CODE_CREATED]: MonacoReducerFunc; public [CommonActionType.EDIT_CELL]: MonacoReducerFunc; - public [CommonActionType.UNMOUNT]: MonacoReducerFunc; + public [CommonActionType.UNMOUNT]: MonacoReducerFunc; } // Create the map between message type and the actual function to call to update state diff --git a/src/datascience-ui/interactive-common/redux/reducers/types.ts b/src/datascience-ui/interactive-common/redux/reducers/types.ts index 9a3f8f893190..bb37cdc248ed 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/types.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/types.ts @@ -4,6 +4,7 @@ import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; import { IShowDataViewer, NativeCommandType } from '../../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { BaseReduxActionPayload } from '../../../../client/datascience/interactive-common/types'; import { ActionWithPayload, ReducerArg } from '../../../react-common/reduxUtils'; import { CursorPos, IMainState } from '../../mainState'; @@ -88,7 +89,14 @@ export interface IShowPlotAction { export interface IScrollAction { isAtBottom: boolean; } -export type CommonReducerArg = ReducerArg; + +// tslint:disable-next-line: no-any +export type PrimitiveTypeInReduxActionPayload = string | number | boolean | Buffer | any[]; +export type CommonReducerArg = T extends never | undefined + ? ReducerArg + : T extends PrimitiveTypeInReduxActionPayload + ? ReducerArg + : ReducerArg; export interface ICellAction { cellId: string | undefined; diff --git a/src/datascience-ui/interactive-common/redux/reducers/variables.ts b/src/datascience-ui/interactive-common/redux/reducers/variables.ts index f48cf215b90a..fb50f749fbea 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/variables.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/variables.ts @@ -3,10 +3,11 @@ 'use strict'; import { Reducer } from 'redux'; import { InteractiveWindowMessages } from '../../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { BaseReduxActionPayload } from '../../../../client/datascience/interactive-common/types'; import { ICell, IJupyterVariable, IJupyterVariablesRequest, IJupyterVariablesResponse } from '../../../../client/datascience/types'; import { combineReducers, QueuableAction, ReducerArg, ReducerFunc } from '../../../react-common/reduxUtils'; import { createPostableAction, IncomingMessageActions } from '../postOffice'; -import { CommonActionType } from './types'; +import { CommonActionType, PrimitiveTypeInReduxActionPayload } from './types'; export type IVariableState = { currentExecutionCount: number; @@ -17,9 +18,17 @@ export type IVariableState = { pageSize: number; }; -type VariableReducerFunc = ReducerFunc; +type VariableReducerFunc = T extends never | undefined + ? ReducerFunc + : T extends PrimitiveTypeInReduxActionPayload + ? ReducerFunc + : ReducerFunc; -type VariableReducerArg = ReducerArg; +type VariableReducerArg = T extends never | undefined + ? ReducerArg + : T extends PrimitiveTypeInReduxActionPayload + ? ReducerArg + : ReducerArg; function handleRequest(arg: VariableReducerArg): IVariableState { const newExecutionCount = arg.payload.executionCount ? arg.payload.executionCount : arg.prevState.currentExecutionCount; @@ -128,9 +137,9 @@ function handleFinishCell(arg: VariableReducerArg): IVariableState { // Create a mapping between message and reducer type class IVariableActionMapping { - public [IncomingMessageActions.RESTARTKERNEL]: VariableReducerFunc; + public [IncomingMessageActions.RESTARTKERNEL]: VariableReducerFunc; public [IncomingMessageActions.FINISHCELL]: VariableReducerFunc; - public [CommonActionType.TOGGLE_VARIABLE_EXPLORER]: VariableReducerFunc; + public [CommonActionType.TOGGLE_VARIABLE_EXPLORER]: VariableReducerFunc; public [CommonActionType.GET_VARIABLE_DATA]: VariableReducerFunc; public [IncomingMessageActions.GETVARIABLESRESPONSE]: VariableReducerFunc; } diff --git a/src/datascience-ui/native-editor/redux/actions.ts b/src/datascience-ui/native-editor/redux/actions.ts index ade4d76b5fde..ad2618b4fb7c 100644 --- a/src/datascience-ui/native-editor/redux/actions.ts +++ b/src/datascience-ui/native-editor/redux/actions.ts @@ -27,7 +27,7 @@ import { // See https://react-redux.js.org/using-react-redux/connect-mapdispatch#defining-mapdispatchtoprops-as-an-object export const actionCreators = { insertAbove: (cellId: string | undefined): CommonAction => ({ type: CommonActionType.INSERT_ABOVE, payload: { cellId, newCellId: uuid() } }), - insertAboveFirst: (): CommonAction => ({ type: CommonActionType.INSERT_ABOVE_FIRST, payload: { newCellId: uuid() } }), + insertAboveFirst: (): CommonAction => ({ type: CommonActionType.INSERT_ABOVE_FIRST, payload: { newCellId: uuid() } }), insertBelow: (cellId: string | undefined): CommonAction => ({ type: CommonActionType.INSERT_BELOW, payload: { cellId, newCellId: uuid() } }), focusCell: (cellId: string, cursorPos: CursorPos = CursorPos.Current): CommonAction => ({ type: CommonActionType.FOCUS_CELL, @@ -38,7 +38,7 @@ export const actionCreators = { type: CommonActionType.SELECT_CELL, payload: { cellId, cursorPos } }), - addCell: (): CommonAction => ({ type: CommonActionType.ADD_NEW_CELL, payload: { newCellId: uuid() } }), + addCell: (): CommonAction => ({ type: CommonActionType.ADD_NEW_CELL, payload: { newCellId: uuid() } }), executeCell: (cellId: string, code: string, moveOp: 'add' | 'select' | 'none'): CommonAction => { if (moveOp === 'add') { return { diff --git a/src/datascience-ui/native-editor/redux/mapping.ts b/src/datascience-ui/native-editor/redux/mapping.ts index f9b33fde953a..4e080a6ff9d6 100644 --- a/src/datascience-ui/native-editor/redux/mapping.ts +++ b/src/datascience-ui/native-editor/redux/mapping.ts @@ -2,6 +2,7 @@ // Licensed under the MIT License. 'use strict'; import { ILoadAllCells } from '../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { BaseReduxActionPayload } from '../../../client/datascience/interactive-common/types'; import { IGetCssResponse } from '../../../client/datascience/messages'; import { IGetMonacoThemeResponse } from '../../../client/datascience/monacoMessages'; import { ICell } from '../../../client/datascience/types'; @@ -19,13 +20,22 @@ import { ILinkClickAction, ISendCommandAction, IShowDataViewerAction, - IShowPlotAction + IShowPlotAction, + PrimitiveTypeInReduxActionPayload } from '../../interactive-common/redux/reducers/types'; import { ReducerArg, ReducerFunc } from '../../react-common/reduxUtils'; -type NativeEditorReducerFunc = ReducerFunc; +type NativeEditorReducerFunc = T extends never | undefined + ? ReducerFunc + : T extends PrimitiveTypeInReduxActionPayload + ? ReducerFunc + : ReducerFunc; -export type NativeEditorReducerArg = ReducerArg; +export type NativeEditorReducerArg = T extends never | undefined + ? ReducerArg + : T extends PrimitiveTypeInReduxActionPayload + ? ReducerArg + : ReducerArg; export class INativeEditorActionMapping { public [CommonActionType.INSERT_ABOVE]: NativeEditorReducerFunc; @@ -35,16 +45,16 @@ export class INativeEditorActionMapping { public [CommonActionType.UNFOCUS_CELL]: NativeEditorReducerFunc; public [CommonActionType.ADD_NEW_CELL]: NativeEditorReducerFunc; public [CommonActionType.EXECUTE_CELL]: NativeEditorReducerFunc; - public [CommonActionType.EXECUTE_ALL_CELLS]: NativeEditorReducerFunc; + public [CommonActionType.EXECUTE_ALL_CELLS]: NativeEditorReducerFunc; public [CommonActionType.EXECUTE_ABOVE]: NativeEditorReducerFunc; public [CommonActionType.EXECUTE_CELL_AND_BELOW]: NativeEditorReducerFunc; - public [CommonActionType.RESTART_KERNEL]: NativeEditorReducerFunc; - public [CommonActionType.INTERRUPT_KERNEL]: NativeEditorReducerFunc; - public [CommonActionType.CLEAR_ALL_OUTPUTS]: NativeEditorReducerFunc; - public [CommonActionType.EXPORT]: NativeEditorReducerFunc; - public [CommonActionType.SAVE]: NativeEditorReducerFunc; - public [CommonActionType.UNDO]: NativeEditorReducerFunc; - public [CommonActionType.REDO]: NativeEditorReducerFunc; + public [CommonActionType.RESTART_KERNEL]: NativeEditorReducerFunc; + public [CommonActionType.INTERRUPT_KERNEL]: NativeEditorReducerFunc; + public [CommonActionType.CLEAR_ALL_OUTPUTS]: NativeEditorReducerFunc; + public [CommonActionType.EXPORT]: NativeEditorReducerFunc; + public [CommonActionType.SAVE]: NativeEditorReducerFunc; + public [CommonActionType.UNDO]: NativeEditorReducerFunc; + public [CommonActionType.REDO]: NativeEditorReducerFunc; public [CommonActionType.SHOW_DATA_VIEWER]: NativeEditorReducerFunc; public [CommonActionType.SEND_COMMAND]: NativeEditorReducerFunc; public [CommonActionType.SELECT_CELL]: NativeEditorReducerFunc; @@ -60,33 +70,33 @@ export class INativeEditorActionMapping { public [CommonActionType.LINK_CLICK]: NativeEditorReducerFunc; public [CommonActionType.SHOW_PLOT]: NativeEditorReducerFunc; public [CommonActionType.GATHER_CELL]: NativeEditorReducerFunc; - public [CommonActionType.EDITOR_LOADED]: NativeEditorReducerFunc; - public [CommonActionType.LOADED_ALL_CELLS]: NativeEditorReducerFunc; - public [CommonActionType.UNMOUNT]: NativeEditorReducerFunc; - public [CommonActionType.SELECT_KERNEL]: NativeEditorReducerFunc; - public [CommonActionType.SELECT_SERVER]: NativeEditorReducerFunc; + public [CommonActionType.EDITOR_LOADED]: NativeEditorReducerFunc; + public [CommonActionType.LOADED_ALL_CELLS]: NativeEditorReducerFunc; + public [CommonActionType.UNMOUNT]: NativeEditorReducerFunc; + public [CommonActionType.SELECT_KERNEL]: NativeEditorReducerFunc; + public [CommonActionType.SELECT_SERVER]: NativeEditorReducerFunc; // Messages from the extension public [IncomingMessageActions.STARTCELL]: NativeEditorReducerFunc; public [IncomingMessageActions.FINISHCELL]: NativeEditorReducerFunc; public [IncomingMessageActions.UPDATECELL]: NativeEditorReducerFunc; - public [IncomingMessageActions.NOTEBOOKDIRTY]: NativeEditorReducerFunc; - public [IncomingMessageActions.NOTEBOOKCLEAN]: NativeEditorReducerFunc; + public [IncomingMessageActions.NOTEBOOKDIRTY]: NativeEditorReducerFunc; + public [IncomingMessageActions.NOTEBOOKCLEAN]: NativeEditorReducerFunc; public [IncomingMessageActions.LOADALLCELLS]: NativeEditorReducerFunc; - public [IncomingMessageActions.NOTEBOOKRUNALLCELLS]: NativeEditorReducerFunc; - public [IncomingMessageActions.NOTEBOOKRUNSELECTEDCELL]: NativeEditorReducerFunc; + public [IncomingMessageActions.NOTEBOOKRUNALLCELLS]: NativeEditorReducerFunc; + public [IncomingMessageActions.NOTEBOOKRUNSELECTEDCELL]: NativeEditorReducerFunc; public [IncomingMessageActions.NOTEBOOKADDCELLBELOW]: NativeEditorReducerFunc; - public [IncomingMessageActions.DOSAVE]: NativeEditorReducerFunc; + public [IncomingMessageActions.DOSAVE]: NativeEditorReducerFunc; public [IncomingMessageActions.DELETEALLCELLS]: NativeEditorReducerFunc; - public [IncomingMessageActions.UNDO]: NativeEditorReducerFunc; - public [IncomingMessageActions.REDO]: NativeEditorReducerFunc; - public [IncomingMessageActions.STARTPROGRESS]: NativeEditorReducerFunc; - public [IncomingMessageActions.STOPPROGRESS]: NativeEditorReducerFunc; + public [IncomingMessageActions.UNDO]: NativeEditorReducerFunc; + public [IncomingMessageActions.REDO]: NativeEditorReducerFunc; + public [IncomingMessageActions.STARTPROGRESS]: NativeEditorReducerFunc; + public [IncomingMessageActions.STOPPROGRESS]: NativeEditorReducerFunc; public [IncomingMessageActions.UPDATESETTINGS]: NativeEditorReducerFunc; - public [IncomingMessageActions.ACTIVATE]: NativeEditorReducerFunc; - public [IncomingMessageActions.RESTARTKERNEL]: NativeEditorReducerFunc; + public [IncomingMessageActions.ACTIVATE]: NativeEditorReducerFunc; + public [IncomingMessageActions.RESTARTKERNEL]: NativeEditorReducerFunc; public [IncomingMessageActions.GETCSSRESPONSE]: NativeEditorReducerFunc; - public [IncomingMessageActions.MONACOREADY]: NativeEditorReducerFunc; + public [IncomingMessageActions.MONACOREADY]: NativeEditorReducerFunc; public [IncomingMessageActions.GETMONACOTHEMERESPONSE]: NativeEditorReducerFunc; public [IncomingMessageActions.UPDATEKERNEL]: NativeEditorReducerFunc; public [IncomingMessageActions.LOCINIT]: NativeEditorReducerFunc; diff --git a/src/datascience-ui/native-editor/redux/reducers/effects.ts b/src/datascience-ui/native-editor/redux/reducers/effects.ts index 65d35324431a..8a72aec1eb08 100644 --- a/src/datascience-ui/native-editor/redux/reducers/effects.ts +++ b/src/datascience-ui/native-editor/redux/reducers/effects.ts @@ -193,7 +193,7 @@ export namespace Effects { export function updateSettings(arg: NativeEditorReducerArg): IMainState { // String arg should be the IDataScienceExtraSettings - const newSettingsJSON = JSON.parse(arg.payload); + const newSettingsJSON = JSON.parse(arg.payload.data); const newSettings = newSettingsJSON; const newEditorOptions = computeEditorOptions(newSettings); const newFontFamily = newSettings.extraSettings ? newSettings.extraSettings.fontFamily : arg.prevState.font.family; diff --git a/src/datascience-ui/react-common/reduxUtils.ts b/src/datascience-ui/react-common/reduxUtils.ts index 1e982cda8506..359fc2c0dfc4 100644 --- a/src/datascience-ui/react-common/reduxUtils.ts +++ b/src/datascience-ui/react-common/reduxUtils.ts @@ -2,6 +2,8 @@ // Licensed under the MIT License. 'use strict'; import { Action, AnyAction, Middleware, Reducer } from 'redux'; +import { BaseReduxActionPayload } from '../../client/datascience/interactive-common/types'; +import { PrimitiveTypeInReduxActionPayload } from '../interactive-common/redux/reducers/types'; // tslint:disable-next-line: interface-name interface TypedAnyAction extends Action { @@ -11,10 +13,11 @@ interface TypedAnyAction extends Action { } export type QueueAnotherFunc = (nextAction: Action) => void; export type QueuableAction = TypedAnyAction & { queueAction: QueueAnotherFunc }; -export type ReducerArg = T extends null | undefined +export type ReducerArg = T extends never | undefined ? { prevState: S; queueAction: QueueAnotherFunc; + payload: BaseReduxActionPayload; } : { prevState: S; @@ -23,8 +26,11 @@ export type ReducerArg = T extends null | undefined }; export type ReducerFunc = (args: ReducerArg) => S; - -export type ActionWithPayload = T extends null | undefined ? TypedAnyAction : TypedAnyAction & { payload: T }; +export type ActionWithPayload = T extends never | undefined + ? TypedAnyAction & { payload?: BaseReduxActionPayload } + : T extends PrimitiveTypeInReduxActionPayload + ? TypedAnyAction & { payload: { data: T } & BaseReduxActionPayload } + : TypedAnyAction & { payload: T & BaseReduxActionPayload }; /** * CombineReducers takes in a map of action.type to func and creates a reducer that will call the appropriate function for From 5b1d4d3c2db999b393e609671581201d49c6007a Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Fri, 31 Jan 2020 15:00:48 -0800 Subject: [PATCH 4/9] Use same message between extension and react ui --- src/client/datascience/data-viewing/types.ts | 24 ++-- .../interactiveWindowTypes.ts | 17 ++- .../datascience/interactive-common/types.ts | 28 +++- src/client/datascience/messages.ts | 20 +-- .../data-explorer/mainPanel.tsx | 2 +- .../history-react/redux/actions.ts | 81 ++++++----- .../history-react/redux/mapping.ts | 86 ++---------- .../history-react/redux/reducers/creation.ts | 19 +-- .../history-react/redux/reducers/effects.ts | 13 +- .../history-react/redux/reducers/execution.ts | 8 +- .../history-react/redux/reducers/index.ts | 57 ++++---- .../interactive-common/redux/postOffice.ts | 103 ++------------ .../redux/reducers/commonEffects.ts | 33 ++--- .../redux/reducers/helpers.ts | 16 +-- .../redux/reducers/kernel.ts | 19 +-- .../redux/reducers/monaco.ts | 71 +++++----- .../redux/reducers/transfer.ts | 60 +++++---- .../redux/reducers/types.ts | 79 +++++++---- .../redux/reducers/variables.ts | 75 +++++------ .../interactive-common/redux/store.ts | 27 ++-- .../native-editor/redux/actions.ts | 126 ++++++++---------- .../native-editor/redux/mapping.ts | 103 ++------------ .../native-editor/redux/reducers/creation.ts | 37 +++-- .../native-editor/redux/reducers/effects.ts | 50 +++---- .../native-editor/redux/reducers/execution.ts | 47 ++++--- .../native-editor/redux/reducers/index.ts | 63 ++++----- .../native-editor/redux/reducers/movement.ts | 24 ++-- src/datascience-ui/plot/mainPanel.tsx | 2 +- src/datascience-ui/react-common/postOffice.ts | 51 +------ src/datascience-ui/react-common/reduxUtils.ts | 10 +- 30 files changed, 565 insertions(+), 786 deletions(-) diff --git a/src/client/datascience/data-viewing/types.ts b/src/client/datascience/data-viewing/types.ts index ed1c240c108c..09751f4daa85 100644 --- a/src/client/datascience/data-viewing/types.ts +++ b/src/client/datascience/data-viewing/types.ts @@ -3,7 +3,7 @@ 'use strict'; import { JSONObject } from '@phosphor/coreutils'; -import { CssMessages, IGetCssRequest, IGetCssResponse, SharedMessages } from '../messages'; +import { SharedMessages } from '../messages'; import { IJupyterVariable } from '../types'; export const CellFetchAllLimit = 100000; @@ -40,15 +40,13 @@ export interface IGetRowsResponse { } // Map all messages to specific payloads -export class IDataViewerMapping { - public [DataViewerMessages.Started]: never | undefined; - public [DataViewerMessages.UpdateSettings]: string; - public [DataViewerMessages.InitializeData]: IJupyterVariable; - public [DataViewerMessages.GetAllRowsRequest]: never | undefined; - public [DataViewerMessages.GetAllRowsResponse]: JSONObject; - public [DataViewerMessages.GetRowsRequest]: IGetRowsRequest; - public [DataViewerMessages.GetRowsResponse]: IGetRowsResponse; - public [DataViewerMessages.CompletedData]: never | undefined; - public [CssMessages.GetCssRequest]: IGetCssRequest; - public [CssMessages.GetCssResponse]: IGetCssResponse; -} +export type IDataViewerMapping = { + [DataViewerMessages.Started]: never | undefined; + [DataViewerMessages.UpdateSettings]: string; + [DataViewerMessages.InitializeData]: IJupyterVariable; + [DataViewerMessages.GetAllRowsRequest]: never | undefined; + [DataViewerMessages.GetAllRowsResponse]: JSONObject; + [DataViewerMessages.GetRowsRequest]: IGetRowsRequest; + [DataViewerMessages.GetRowsResponse]: IGetRowsResponse; + [DataViewerMessages.CompletedData]: never | undefined; +}; diff --git a/src/client/datascience/interactive-common/interactiveWindowTypes.ts b/src/client/datascience/interactive-common/interactiveWindowTypes.ts index 0a7e6eb2deb8..fe4641254bf9 100644 --- a/src/client/datascience/interactive-common/interactiveWindowTypes.ts +++ b/src/client/datascience/interactive-common/interactiveWindowTypes.ts @@ -3,8 +3,9 @@ 'use strict'; import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; import { IServerState } from '../../../datascience-ui/interactive-common/mainState'; -import { IAddCellAction } from '../../../datascience-ui/interactive-common/redux/reducers/types'; -import { CssMessages, IGetCssRequest, IGetCssResponse, IGetMonacoThemeRequest } from '../messages'; +import { IAddCellAction, ICellAction } from '../../../datascience-ui/interactive-common/redux/reducers/types'; +import { CssMessages, IGetCssRequest, IGetCssResponse, IGetMonacoThemeRequest, SharedMessages } from '../messages'; +import { IGetMonacoThemeResponse } from '../monacoMessages'; import { ICell, IInteractiveWindowInfo, IJupyterVariable, IJupyterVariablesRequest, IJupyterVariablesResponse } from '../types'; export enum InteractiveWindowMessages { @@ -305,9 +306,9 @@ export class IInteractiveWindowMapping { public [InteractiveWindowMessages.SelectKernel]: IServerState | undefined; public [InteractiveWindowMessages.SelectJupyterServer]: never | undefined; public [InteractiveWindowMessages.Export]: ICell[]; - public [InteractiveWindowMessages.GetAllCells]: ICell; + public [InteractiveWindowMessages.GetAllCells]: never | undefined; public [InteractiveWindowMessages.ReturnAllCells]: ICell[]; - public [InteractiveWindowMessages.DeleteCell]: never | undefined; + public [InteractiveWindowMessages.DeleteCell]: ICellAction; public [InteractiveWindowMessages.DeleteAllCells]: IAddCellAction; public [InteractiveWindowMessages.Undo]: never | undefined; public [InteractiveWindowMessages.Redo]: never | undefined; @@ -331,6 +332,7 @@ export class IInteractiveWindowMapping { public [CssMessages.GetCssRequest]: IGetCssRequest; public [CssMessages.GetCssResponse]: IGetCssResponse; public [CssMessages.GetMonacoThemeRequest]: IGetMonacoThemeRequest; + public [CssMessages.GetMonacoThemeResponse]: IGetMonacoThemeResponse; public [InteractiveWindowMessages.ProvideCompletionItemsRequest]: IProvideCompletionItemsRequest; public [InteractiveWindowMessages.CancelCompletionItemsRequest]: ICancelIntellisenseRequest; public [InteractiveWindowMessages.ProvideCompletionItemsResponse]: IProvideCompletionItemsResponse; @@ -370,11 +372,14 @@ export class IInteractiveWindowMapping { public [InteractiveWindowMessages.VariablesComplete]: never | undefined; public [InteractiveWindowMessages.NotebookRunAllCells]: never | undefined; public [InteractiveWindowMessages.NotebookRunSelectedCell]: never | undefined; - public [InteractiveWindowMessages.NotebookAddCellBelow]: never | undefined; + public [InteractiveWindowMessages.NotebookAddCellBelow]: IAddCellAction; + public [InteractiveWindowMessages.DoSave]: never | undefined; public [InteractiveWindowMessages.ExecutionRendered]: IRenderComplete; public [InteractiveWindowMessages.FocusedCellEditor]: IFocusedCellEditor; public [InteractiveWindowMessages.UnfocusedCellEditor]: never | undefined; public [InteractiveWindowMessages.MonacoReady]: never | undefined; public [InteractiveWindowMessages.ClearAllOutputs]: never | undefined; - public [InteractiveWindowMessages.UpdateKernel]: IServerState | undefined; + public [InteractiveWindowMessages.UpdateKernel]: IServerState; + public [SharedMessages.UpdateSettings]: string; + public [SharedMessages.LocInit]: string; } diff --git a/src/client/datascience/interactive-common/types.ts b/src/client/datascience/interactive-common/types.ts index 3119b447cda7..590bd60fb178 100644 --- a/src/client/datascience/interactive-common/types.ts +++ b/src/client/datascience/interactive-common/types.ts @@ -5,8 +5,7 @@ // Stuff common to React and Extensions. -// This forms the base content of every payload in all dispatchers. -export type BaseReduxActionPayload = { +type BaseData = { /** * If this property exists, then this is an action that has been dispatched for the solve purpose of: * 1. Synchronizing states across different editors (pointing to the same file). @@ -15,4 +14,29 @@ export type BaseReduxActionPayload = { * @type {('syncEditors' | 'syncSessions')} */ broadcastReason?: 'syncEditors' | 'syncSessions'; + /** + * Tells us whether this message is incoming for reducer use or + * whether this is a message that needs to be sent out to extension (from reducer). + */ + messageDirection?: 'incoming' | 'outgoing'; }; + +type BaseDataWithPayload = { + /** + * If this property exists, then this is an action that has been dispatched for the solve purpose of: + * 1. Synchronizing states across different editors (pointing to the same file). + * 2. Synchronizing states across different editors (pointing to the same file) in different sessions. + * + * @type {('syncEditors' | 'syncSessions')} + */ + broadcastReason?: 'syncEditors' | 'syncSessions'; + /** + * Tells us whether this message is incoming for reducer use or + * whether this is a message that needs to be sent out to extension (from reducer). + */ + messageDirection?: 'incoming' | 'outgoing'; + data: T; +}; + +// This forms the base content of every payload in all dispatchers. +export type BaseReduxActionPayload = T extends never ? (T extends undefined ? BaseData : BaseDataWithPayload) : BaseDataWithPayload; diff --git a/src/client/datascience/messages.ts b/src/client/datascience/messages.ts index b2d17ad18404..c7e7ca14dcf8 100644 --- a/src/client/datascience/messages.ts +++ b/src/client/datascience/messages.ts @@ -2,18 +2,18 @@ // Licensed under the MIT License. 'use strict'; -export namespace CssMessages { - export const GetCssRequest = 'get_css_request'; - export const GetCssResponse = 'get_css_response'; - export const GetMonacoThemeRequest = 'get_monaco_theme_request'; - export const GetMonacoThemeResponse = 'get_monaco_theme_response'; +export enum CssMessages { + GetCssRequest = 'get_css_request', + GetCssResponse = 'get_css_response', + GetMonacoThemeRequest = 'get_monaco_theme_request', + GetMonacoThemeResponse = 'get_monaco_theme_response' } -export namespace SharedMessages { - export const UpdateSettings = 'update_settings'; - export const Started = 'started'; - export const LocInit = 'loc_init'; - export const StyleUpdate = 'style_update'; +export enum SharedMessages { + UpdateSettings = 'update_settings', + Started = 'started', + LocInit = 'loc_init', + StyleUpdate = 'style_update' } export interface IGetCssRequest { diff --git a/src/datascience-ui/data-explorer/mainPanel.tsx b/src/datascience-ui/data-explorer/mainPanel.tsx index eaf9d69ed840..ea6eeeac2adf 100644 --- a/src/datascience-ui/data-explorer/mainPanel.tsx +++ b/src/datascience-ui/data-explorer/mainPanel.tsx @@ -94,7 +94,7 @@ export class MainPanel extends React.Component this.postOffice.addHandler(this); // Tell the dataviewer code we have started. - this.postOffice.sendMessage(DataViewerMessages.Started); + this.postOffice.sendMessage(DataViewerMessages.Started); } public componentWillUnmount() { diff --git a/src/datascience-ui/history-react/redux/actions.ts b/src/datascience-ui/history-react/redux/actions.ts index 94ccc0aa57f9..b6f55eaec82d 100644 --- a/src/datascience-ui/history-react/redux/actions.ts +++ b/src/datascience-ui/history-react/redux/actions.ts @@ -3,60 +3,57 @@ 'use strict'; import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; -import { IRefreshVariablesRequest } from '../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { InteractiveWindowMessages, IRefreshVariablesRequest } from '../../../client/datascience/interactive-common/interactiveWindowTypes'; import { IJupyterVariable, IJupyterVariablesRequest } from '../../../client/datascience/types'; import { CommonAction, CommonActionType, + createIncomingAction, + createIncomingActionWithPayload, ICellAction, ICodeAction, ICodeCreatedAction, IEditCellAction, ILinkClickAction, IScrollAction, - IShowDataViewerAction, - IShowPlotAction + IShowDataViewerAction } from '../../interactive-common/redux/reducers/types'; // See https://react-redux.js.org/using-react-redux/connect-mapdispatch#defining-mapdispatchtoprops-as-an-object export const actionCreators = { - refreshVariables: (newExecutionCount?: number): CommonAction => ({ type: CommonActionType.REFRESH_VARIABLES, payload: { newExecutionCount } }), - restartKernel: (): CommonAction => ({ type: CommonActionType.RESTART_KERNEL }), - interruptKernel: (): CommonAction => ({ type: CommonActionType.INTERRUPT_KERNEL }), - deleteAllCells: (): CommonAction => ({ type: CommonActionType.DELETE_ALL_CELLS }), - deleteCell: (cellId: string): CommonAction => ({ type: CommonActionType.DELETE_CELL, payload: { cellId } }), - undo: (): CommonAction => ({ type: CommonActionType.UNDO }), - redo: (): CommonAction => ({ type: CommonActionType.REDO }), - linkClick: (href: string): CommonAction => ({ type: CommonActionType.LINK_CLICK, payload: { href } }), - showPlot: (imageHtml: string): CommonAction => ({ type: CommonActionType.SHOW_PLOT, payload: { imageHtml } }), - toggleInputBlock: (cellId: string): CommonAction => ({ type: CommonActionType.TOGGLE_INPUT_BLOCK, payload: { cellId } }), - gotoCell: (cellId: string): CommonAction => ({ type: CommonActionType.GOTO_CELL, payload: { cellId } }), - copyCellCode: (cellId: string): CommonAction => ({ type: CommonActionType.COPY_CELL_CODE, payload: { cellId } }), - gatherCell: (cellId: string): CommonAction => ({ type: CommonActionType.GATHER_CELL, payload: { cellId } }), - clickCell: (cellId: string): CommonAction => ({ type: CommonActionType.CLICK_CELL, payload: { cellId } }), - doubleClickCell: (cellId: string): CommonAction => ({ type: CommonActionType.DOUBLE_CLICK_CELL, payload: { cellId } }), - editCell: (cellId: string, changes: monacoEditor.editor.IModelContentChange[], modelId: string, code: string): CommonAction => ({ - type: CommonActionType.EDIT_CELL, - payload: { cellId, changes, modelId, code } - }), - submitInput: (code: string, cellId: string): CommonAction => ({ type: CommonActionType.SUBMIT_INPUT, payload: { code, cellId } }), - toggleVariableExplorer: (): CommonAction => ({ type: CommonActionType.TOGGLE_VARIABLE_EXPLORER }), - expandAll: (): CommonAction => ({ type: CommonActionType.EXPAND_ALL }), - collapseAll: (): CommonAction => ({ type: CommonActionType.COLLAPSE_ALL }), - export: (): CommonAction => ({ type: CommonActionType.EXPORT }), - showDataViewer: (variable: IJupyterVariable, columnSize: number): CommonAction => ({ - type: CommonActionType.SHOW_DATA_VIEWER, - payload: { variable, columnSize } - }), - editorLoaded: (): CommonAction => ({ type: CommonActionType.EDITOR_LOADED }), - scroll: (isAtBottom: boolean): CommonAction => ({ type: CommonActionType.SCROLL, payload: { isAtBottom } }), - unfocus: (cellId: string | undefined): CommonAction => ({ type: CommonActionType.UNFOCUS_CELL, payload: { cellId } }), - codeCreated: (cellId: string | undefined, modelId: string): CommonAction => ({ type: CommonActionType.CODE_CREATED, payload: { cellId, modelId } }), - editorUnmounted: (): CommonAction => ({ type: CommonActionType.UNMOUNT }), - selectKernel: (): CommonAction => ({ type: CommonActionType.SELECT_KERNEL }), - selectServer: (): CommonAction => ({ type: CommonActionType.SELECT_SERVER }), - getVariableData: (newExecutionCount: number, startIndex: number = 0, pageSize: number = 100): CommonAction => ({ - type: CommonActionType.GET_VARIABLE_DATA, - payload: { executionCount: newExecutionCount, sortColumn: 'name', sortAscending: true, startIndex, pageSize } - }) + refreshVariables: (newExecutionCount?: number): CommonAction => + createIncomingActionWithPayload(CommonActionType.REFRESH_VARIABLES, { newExecutionCount }), + restartKernel: (): CommonAction => createIncomingAction(CommonActionType.RESTART_KERNEL), + interruptKernel: (): CommonAction => createIncomingAction(CommonActionType.INTERRUPT_KERNEL), + deleteAllCells: (): CommonAction => createIncomingAction(InteractiveWindowMessages.DeleteAllCells), + deleteCell: (cellId: string): CommonAction => createIncomingActionWithPayload(InteractiveWindowMessages.DeleteCell, { cellId }), + undo: (): CommonAction => createIncomingAction(InteractiveWindowMessages.Undo), + redo: (): CommonAction => createIncomingAction(InteractiveWindowMessages.Redo), + linkClick: (href: string): CommonAction => createIncomingActionWithPayload(CommonActionType.LINK_CLICK, { href }), + showPlot: (imageHtml: string): CommonAction => createIncomingActionWithPayload(InteractiveWindowMessages.ShowPlot, imageHtml), + toggleInputBlock: (cellId: string): CommonAction => createIncomingActionWithPayload(CommonActionType.TOGGLE_INPUT_BLOCK, { cellId }), + gotoCell: (cellId: string): CommonAction => createIncomingActionWithPayload(CommonActionType.GOTO_CELL, { cellId }), + copyCellCode: (cellId: string): CommonAction => createIncomingActionWithPayload(CommonActionType.COPY_CELL_CODE, { cellId }), + gatherCell: (cellId: string): CommonAction => createIncomingActionWithPayload(CommonActionType.GATHER_CELL, { cellId }), + clickCell: (cellId: string): CommonAction => createIncomingActionWithPayload(CommonActionType.CLICK_CELL, { cellId }), + doubleClickCell: (cellId: string): CommonAction => createIncomingActionWithPayload(CommonActionType.DOUBLE_CLICK_CELL, { cellId }), + editCell: (cellId: string, changes: monacoEditor.editor.IModelContentChange[], modelId: string, code: string): CommonAction => + createIncomingActionWithPayload(CommonActionType.EDIT_CELL, { cellId, changes, modelId, code }), + submitInput: (code: string, cellId: string): CommonAction => createIncomingActionWithPayload(CommonActionType.SUBMIT_INPUT, { code, cellId }), + toggleVariableExplorer: (): CommonAction => createIncomingAction(CommonActionType.TOGGLE_VARIABLE_EXPLORER), + expandAll: (): CommonAction => createIncomingAction(InteractiveWindowMessages.ExpandAll), + collapseAll: (): CommonAction => createIncomingAction(InteractiveWindowMessages.CollapseAll), + export: (): CommonAction => createIncomingAction(CommonActionType.EXPORT), + showDataViewer: (variable: IJupyterVariable, columnSize: number): CommonAction => + createIncomingActionWithPayload(CommonActionType.SHOW_DATA_VIEWER, { variable, columnSize }), + editorLoaded: (): CommonAction => createIncomingAction(CommonActionType.EDITOR_LOADED), + scroll: (isAtBottom: boolean): CommonAction => createIncomingActionWithPayload(CommonActionType.SCROLL, { isAtBottom }), + unfocus: (cellId: string | undefined): CommonAction => createIncomingActionWithPayload(CommonActionType.UNFOCUS_CELL, { cellId }), + codeCreated: (cellId: string | undefined, modelId: string): CommonAction => + createIncomingActionWithPayload(CommonActionType.CODE_CREATED, { cellId, modelId }), + editorUnmounted: (): CommonAction => createIncomingAction(CommonActionType.UNMOUNT), + selectKernel: (): CommonAction => createIncomingAction(InteractiveWindowMessages.SelectKernel), + selectServer: (): CommonAction => createIncomingAction(CommonActionType.SELECT_SERVER), + getVariableData: (newExecutionCount: number, startIndex: number = 0, pageSize: number = 100): CommonAction => + createIncomingActionWithPayload(CommonActionType.GET_VARIABLE_DATA, { executionCount: newExecutionCount, sortColumn: 'name', sortAscending: true, startIndex, pageSize }) }; diff --git a/src/datascience-ui/history-react/redux/mapping.ts b/src/datascience-ui/history-react/redux/mapping.ts index a169b127268c..8856ea8a3d52 100644 --- a/src/datascience-ui/history-react/redux/mapping.ts +++ b/src/datascience-ui/history-react/redux/mapping.ts @@ -1,86 +1,18 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. 'use strict'; -import { IScrollToCell } from '../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { IInteractiveWindowMapping, InteractiveWindowMessages } from '../../../client/datascience/interactive-common/interactiveWindowTypes'; import { BaseReduxActionPayload } from '../../../client/datascience/interactive-common/types'; -import { IGetCssResponse } from '../../../client/datascience/messages'; -import { IGetMonacoThemeResponse } from '../../../client/datascience/monacoMessages'; -import { ICell } from '../../../client/datascience/types'; -import { IMainState, IServerState } from '../../interactive-common/mainState'; -import { IncomingMessageActions } from '../../interactive-common/redux/postOffice'; -import { - CommonActionType, - IAddCellAction, - ICellAction, - ICodeAction, - IEditCellAction, - ILinkClickAction, - IScrollAction, - IShowDataViewerAction, - IShowPlotAction, - PrimitiveTypeInReduxActionPayload -} from '../../interactive-common/redux/reducers/types'; +import { IMainState } from '../../interactive-common/mainState'; +import { CommonActionType, CommonActionTypeMapping } from '../../interactive-common/redux/reducers/types'; import { ReducerArg, ReducerFunc } from '../../react-common/reduxUtils'; -type InteractiveReducerFunc = T extends never | undefined - ? ReducerFunc - : T extends PrimitiveTypeInReduxActionPayload - ? ReducerFunc - : ReducerFunc; +export type InteractiveReducerFunc = ReducerFunc>; -export type InteractiveReducerArg = T extends never | undefined - ? ReducerArg - : T extends PrimitiveTypeInReduxActionPayload - ? ReducerArg - : ReducerArg; +export type InteractiveReducerArg = ReducerArg>; -export class IInteractiveActionMapping { - public [CommonActionType.RESTART_KERNEL]: InteractiveReducerFunc; - public [CommonActionType.SELECT_KERNEL]: InteractiveReducerFunc; - public [CommonActionType.SELECT_SERVER]: InteractiveReducerFunc; - public [CommonActionType.INTERRUPT_KERNEL]: InteractiveReducerFunc; - public [CommonActionType.EXPORT]: InteractiveReducerFunc; - public [CommonActionType.SAVE]: InteractiveReducerFunc; - public [CommonActionType.UNDO]: InteractiveReducerFunc; - public [CommonActionType.REDO]: InteractiveReducerFunc; - public [CommonActionType.SHOW_DATA_VIEWER]: InteractiveReducerFunc; - public [CommonActionType.DELETE_CELL]: InteractiveReducerFunc; - public [CommonActionType.LINK_CLICK]: InteractiveReducerFunc; - public [CommonActionType.SHOW_PLOT]: InteractiveReducerFunc; - public [CommonActionType.TOGGLE_INPUT_BLOCK]: InteractiveReducerFunc; - public [CommonActionType.GOTO_CELL]: InteractiveReducerFunc; - public [CommonActionType.COPY_CELL_CODE]: InteractiveReducerFunc; - public [CommonActionType.GATHER_CELL]: InteractiveReducerFunc; - public [CommonActionType.EDIT_CELL]: InteractiveReducerFunc; - public [CommonActionType.SUBMIT_INPUT]: InteractiveReducerFunc; - public [CommonActionType.DELETE_ALL_CELLS]: InteractiveReducerFunc; - public [CommonActionType.EXPAND_ALL]: InteractiveReducerFunc; - public [CommonActionType.COLLAPSE_ALL]: InteractiveReducerFunc; - public [CommonActionType.EDITOR_LOADED]: InteractiveReducerFunc; - public [CommonActionType.SCROLL]: InteractiveReducerFunc; - public [CommonActionType.CLICK_CELL]: InteractiveReducerFunc; - public [CommonActionType.UNFOCUS_CELL]: InteractiveReducerFunc; - public [CommonActionType.UNMOUNT]: InteractiveReducerFunc; +type InteractiveWindowReducerFunctions = { + [P in keyof T]: T[P] extends never | undefined ? InteractiveReducerFunc : InteractiveReducerFunc; +}; - // Messages from the extension - public [IncomingMessageActions.STARTCELL]: InteractiveReducerFunc; - public [IncomingMessageActions.FINISHCELL]: InteractiveReducerFunc; - public [IncomingMessageActions.UPDATECELL]: InteractiveReducerFunc; - public [IncomingMessageActions.ACTIVATE]: InteractiveReducerFunc; - public [IncomingMessageActions.RESTARTKERNEL]: InteractiveReducerFunc; - public [IncomingMessageActions.GETCSSRESPONSE]: InteractiveReducerFunc; - public [IncomingMessageActions.MONACOREADY]: InteractiveReducerFunc; - public [IncomingMessageActions.GETMONACOTHEMERESPONSE]: InteractiveReducerFunc; - public [IncomingMessageActions.GETALLCELLS]: InteractiveReducerFunc; - public [IncomingMessageActions.EXPANDALL]: InteractiveReducerFunc; - public [IncomingMessageActions.COLLAPSEALL]: InteractiveReducerFunc; - public [IncomingMessageActions.DELETEALLCELLS]: InteractiveReducerFunc; - public [IncomingMessageActions.STARTPROGRESS]: InteractiveReducerFunc; - public [IncomingMessageActions.STOPPROGRESS]: InteractiveReducerFunc; - public [IncomingMessageActions.UPDATESETTINGS]: InteractiveReducerFunc; - public [IncomingMessageActions.STARTDEBUGGING]: InteractiveReducerFunc; - public [IncomingMessageActions.STOPDEBUGGING]: InteractiveReducerFunc; - public [IncomingMessageActions.SCROLLTOCELL]: InteractiveReducerFunc; - public [IncomingMessageActions.UPDATEKERNEL]: InteractiveReducerFunc; - public [IncomingMessageActions.LOCINIT]: InteractiveReducerFunc; -} +export type IInteractiveActionMapping = InteractiveWindowReducerFunctions & InteractiveWindowReducerFunctions; diff --git a/src/datascience-ui/history-react/redux/reducers/creation.ts b/src/datascience-ui/history-react/redux/reducers/creation.ts index f06baaf97874..1ecd2bbedaba 100644 --- a/src/datascience-ui/history-react/redux/reducers/creation.ts +++ b/src/datascience-ui/history-react/redux/reducers/creation.ts @@ -7,7 +7,7 @@ import { ICell, IDataScienceExtraSettings } from '../../../../client/datascience import { createCellVM, extractInputText, ICellViewModel, IMainState } from '../../../interactive-common/mainState'; import { createPostableAction } from '../../../interactive-common/redux/postOffice'; import { Helpers } from '../../../interactive-common/redux/reducers/helpers'; -import { ICellAction } from '../../../interactive-common/redux/reducers/types'; +import { IAddCellAction, ICellAction } from '../../../interactive-common/redux/reducers/types'; import { InteractiveReducerArg } from '../mapping'; export namespace Creation { @@ -79,9 +79,9 @@ export namespace Creation { } export function startCell(arg: InteractiveReducerArg): IMainState { - if (isCellSupported(arg.prevState, arg.payload)) { + if (isCellSupported(arg.prevState, arg.payload.data)) { const result = Helpers.updateOrAdd(arg, prepareCellVM); - if (result.cellVMs.length > arg.prevState.cellVMs.length && arg.payload.id !== Identifiers.EditCellId) { + if (result.cellVMs.length > arg.prevState.cellVMs.length && arg.payload.data.id !== Identifiers.EditCellId) { const cellVM = result.cellVMs[result.cellVMs.length - 1]; // We're adding a new cell here. Tell the intellisense engine we have a new cell @@ -100,20 +100,21 @@ export namespace Creation { } export function updateCell(arg: InteractiveReducerArg): IMainState { - if (isCellSupported(arg.prevState, arg.payload)) { + if (isCellSupported(arg.prevState, arg.payload.data)) { return Helpers.updateOrAdd(arg, prepareCellVM); } return arg.prevState; } export function finishCell(arg: InteractiveReducerArg): IMainState { - if (isCellSupported(arg.prevState, arg.payload)) { + if (isCellSupported(arg.prevState, arg.payload.data)) { return Helpers.updateOrAdd(arg, prepareCellVM); } return arg.prevState; } - export function deleteAllCells(arg: InteractiveReducerArg): IMainState { + export function deleteAllCells(arg: InteractiveReducerArg): IMainState { + // TODO: In Native Editor, we create a new blank cell, don't we need that here? // Send messages to other side to indicate the deletes arg.queueAction(createPostableAction(InteractiveWindowMessages.DeleteAllCells)); @@ -127,11 +128,11 @@ export namespace Creation { } export function deleteCell(arg: InteractiveReducerArg): IMainState { - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); - if (index >= 0 && arg.payload.cellId) { + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); + if (index >= 0 && arg.payload.data.cellId) { // Send messages to other side to indicate the delete arg.queueAction(createPostableAction(InteractiveWindowMessages.DeleteCell)); - arg.queueAction(createPostableAction(InteractiveWindowMessages.RemoveCell, { id: arg.payload.cellId })); + arg.queueAction(createPostableAction(InteractiveWindowMessages.RemoveCell, { id: arg.payload.data.cellId })); const newVMs = arg.prevState.cellVMs.filter((_c, i) => i !== index); return { diff --git a/src/datascience-ui/history-react/redux/reducers/effects.ts b/src/datascience-ui/history-react/redux/reducers/effects.ts index 288947c00065..f854dcf19391 100644 --- a/src/datascience-ui/history-react/redux/reducers/effects.ts +++ b/src/datascience-ui/history-react/redux/reducers/effects.ts @@ -37,9 +37,9 @@ export namespace Effects { } export function toggleInputBlock(arg: InteractiveReducerArg): IMainState { - if (arg.payload.cellId) { + if (arg.payload.data.cellId) { const newVMs = [...arg.prevState.cellVMs]; - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); const oldVM = arg.prevState.cellVMs[index]; newVMs[index] = Creation.alterCellVM({ ...oldVM }, arg.prevState.settings, true, !oldVM.inputBlockOpen); return { @@ -51,6 +51,7 @@ export namespace Effects { } export function updateSettings(arg: InteractiveReducerArg): IMainState { + console.error(`Settings Message ${arg.payload}`); // String arg should be the IDataScienceExtraSettings const newSettingsJSON = JSON.parse(arg.payload.data); const newSettings = newSettingsJSON; @@ -86,7 +87,7 @@ export namespace Effects { export function scrollToCell(arg: InteractiveReducerArg): IMainState { // Up the scroll count on the necessary cell - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.id); + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.id); if (index >= 0) { const newVMs = [...arg.prevState.cellVMs]; @@ -105,12 +106,12 @@ export namespace Effects { export function scrolled(arg: InteractiveReducerArg): IMainState { return { ...arg.prevState, - isAtBottom: arg.payload.isAtBottom + isAtBottom: arg.payload.data.isAtBottom }; } export function clickCell(arg: InteractiveReducerArg): IMainState { - if (arg.payload.cellId === Identifiers.EditCellId && arg.prevState.editCellVM && !arg.prevState.editCellVM.focused) { + if (arg.payload.data.cellId === Identifiers.EditCellId && arg.prevState.editCellVM && !arg.prevState.editCellVM.focused) { return { ...arg.prevState, editCellVM: { @@ -132,7 +133,7 @@ export namespace Effects { } export function unfocusCell(arg: InteractiveReducerArg): IMainState { - if (arg.payload.cellId === Identifiers.EditCellId && arg.prevState.editCellVM && arg.prevState.editCellVM.focused) { + if (arg.payload.data.cellId === Identifiers.EditCellId && arg.prevState.editCellVM && arg.prevState.editCellVM.focused) { return { ...arg.prevState, editCellVM: { diff --git a/src/datascience-ui/history-react/redux/reducers/execution.ts b/src/datascience-ui/history-react/redux/reducers/execution.ts index 264e9461dcc8..6f38f4e8f08e 100644 --- a/src/datascience-ui/history-react/redux/reducers/execution.ts +++ b/src/datascience-ui/history-react/redux/reducers/execution.ts @@ -79,16 +79,16 @@ export namespace Execution { export function submitInput(arg: InteractiveReducerArg): IMainState { // noop if the submitted code is just a cell marker const matcher = new CellMatcher(arg.prevState.settings); - if (matcher.stripFirstMarker(arg.payload.code).length > 0 && arg.prevState.editCellVM) { + if (matcher.stripFirstMarker(arg.payload.data.code).length > 0 && arg.prevState.editCellVM) { // This should be from the edit cell VM. Copy it and change the cell id let newCell = cloneDeep(arg.prevState.editCellVM); // Change this editable cell to not editable. newCell.cell.state = CellState.executing; - newCell.cell.data.source = arg.payload.code; + newCell.cell.data.source = arg.payload.data.code; // Change type to markdown if necessary - const split = arg.payload.code.splitLines({ trim: false }); + const split = arg.payload.data.code.splitLines({ trim: false }); const firstLine = split[0]; if (matcher.isMarkdown(firstLine)) { newCell.cell.data = createCellFrom(newCell.cell.data, 'markdown'); @@ -113,7 +113,7 @@ export namespace Execution { // Send a message to execute this code if necessary. if (newCell.cell.state !== CellState.finished) { - arg.queueAction(createPostableAction(InteractiveWindowMessages.SubmitNewCell, { code: arg.payload.code, id: newCell.cell.id })); + arg.queueAction(createPostableAction(InteractiveWindowMessages.SubmitNewCell, { code: arg.payload.data.code, id: newCell.cell.id })); } // Stick in a new cell at the bottom that's editable and update our state diff --git a/src/datascience-ui/history-react/redux/reducers/index.ts b/src/datascience-ui/history-react/redux/reducers/index.ts index da3703085aae..3cbc55f3475a 100644 --- a/src/datascience-ui/history-react/redux/reducers/index.ts +++ b/src/datascience-ui/history-react/redux/reducers/index.ts @@ -1,7 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. 'use strict'; -import { IncomingMessageActions } from '../../../interactive-common/redux/postOffice'; +import { InteractiveWindowMessages } from '../../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { CssMessages, SharedMessages } from '../../../../client/datascience/messages'; import { CommonEffects } from '../../../interactive-common/redux/reducers/commonEffects'; import { Kernel } from '../../../interactive-common/redux/reducers/kernel'; import { Transfer } from '../../../interactive-common/redux/reducers/transfer'; @@ -12,19 +13,17 @@ import { Effects } from './effects'; import { Execution } from './execution'; // The list of reducers. 1 per message/action. -export const reducerMap: IInteractiveActionMapping = { +export const reducerMap: Partial = { // State updates [CommonActionType.RESTART_KERNEL]: Kernel.restartKernel, [CommonActionType.INTERRUPT_KERNEL]: Kernel.interruptKernel, - [CommonActionType.SELECT_KERNEL]: Kernel.selectKernel, + [InteractiveWindowMessages.SelectKernel]: Kernel.selectKernel, [CommonActionType.SELECT_SERVER]: Kernel.selectJupyterURI, [CommonActionType.EXPORT]: Transfer.exportCells, [CommonActionType.SAVE]: Transfer.save, [CommonActionType.SHOW_DATA_VIEWER]: Transfer.showDataViewer, - [CommonActionType.DELETE_CELL]: Creation.deleteCell, - [CommonActionType.UNDO]: Execution.undo, - [CommonActionType.REDO]: Execution.redo, - [CommonActionType.SHOW_PLOT]: Transfer.showPlot, + [InteractiveWindowMessages.DeleteCell]: Creation.deleteCell, + [InteractiveWindowMessages.ShowPlot]: Transfer.showPlot, [CommonActionType.LINK_CLICK]: Transfer.linkClick, [CommonActionType.GOTO_CELL]: Transfer.gotoCell, [CommonActionType.TOGGLE_INPUT_BLOCK]: Effects.toggleInputBlock, @@ -32,9 +31,7 @@ export const reducerMap: IInteractiveActionMapping = { [CommonActionType.GATHER_CELL]: Transfer.gather, [CommonActionType.EDIT_CELL]: Transfer.editCell, [CommonActionType.SUBMIT_INPUT]: Execution.submitInput, - [CommonActionType.DELETE_ALL_CELLS]: Creation.deleteAllCells, - [CommonActionType.EXPAND_ALL]: Effects.expandAll, - [CommonActionType.COLLAPSE_ALL]: Effects.collapseAll, + [InteractiveWindowMessages.ExpandAll]: Effects.expandAll, [CommonActionType.EDITOR_LOADED]: Transfer.started, [CommonActionType.SCROLL]: Effects.scrolled, [CommonActionType.CLICK_CELL]: Effects.clickCell, @@ -42,24 +39,24 @@ export const reducerMap: IInteractiveActionMapping = { [CommonActionType.UNMOUNT]: Creation.unmount, // Messages from the webview (some are ignored) - [IncomingMessageActions.STARTCELL]: Creation.startCell, - [IncomingMessageActions.FINISHCELL]: Creation.finishCell, - [IncomingMessageActions.UPDATECELL]: Creation.updateCell, - [IncomingMessageActions.ACTIVATE]: CommonEffects.activate, - [IncomingMessageActions.RESTARTKERNEL]: Kernel.handleRestarted, - [IncomingMessageActions.GETCSSRESPONSE]: CommonEffects.handleCss, - [IncomingMessageActions.MONACOREADY]: CommonEffects.monacoReady, - [IncomingMessageActions.GETMONACOTHEMERESPONSE]: CommonEffects.monacoThemeChange, - [IncomingMessageActions.GETALLCELLS]: Transfer.getAllCells, - [IncomingMessageActions.EXPANDALL]: Effects.expandAll, - [IncomingMessageActions.COLLAPSEALL]: Effects.collapseAll, - [IncomingMessageActions.DELETEALLCELLS]: Creation.deleteAllCells, - [IncomingMessageActions.STARTPROGRESS]: CommonEffects.startProgress, - [IncomingMessageActions.STOPPROGRESS]: CommonEffects.stopProgress, - [IncomingMessageActions.UPDATESETTINGS]: Effects.updateSettings, - [IncomingMessageActions.STARTDEBUGGING]: Execution.startDebugging, - [IncomingMessageActions.STOPDEBUGGING]: Execution.stopDebugging, - [IncomingMessageActions.SCROLLTOCELL]: Effects.scrollToCell, - [IncomingMessageActions.UPDATEKERNEL]: Kernel.updateStatus, - [IncomingMessageActions.LOCINIT]: CommonEffects.handleLocInit + [InteractiveWindowMessages.StartCell]: Creation.startCell, + [InteractiveWindowMessages.FinishCell]: Creation.finishCell, + [InteractiveWindowMessages.UpdateCell]: Creation.updateCell, + [InteractiveWindowMessages.Activate]: CommonEffects.activate, + [InteractiveWindowMessages.RestartKernel]: Kernel.handleRestarted, + [CssMessages.GetCssResponse]: CommonEffects.handleCss, + [InteractiveWindowMessages.MonacoReady]: CommonEffects.monacoReady, + [CssMessages.GetMonacoThemeResponse]: CommonEffects.monacoThemeChange, + [InteractiveWindowMessages.GetAllCells]: Transfer.getAllCells, + [InteractiveWindowMessages.ExpandAll]: Effects.expandAll, + [InteractiveWindowMessages.CollapseAll]: Effects.collapseAll, + [InteractiveWindowMessages.DeleteAllCells]: Creation.deleteAllCells, + [InteractiveWindowMessages.StartProgress]: CommonEffects.startProgress, + [InteractiveWindowMessages.StopProgress]: CommonEffects.stopProgress, + [SharedMessages.UpdateSettings]: Effects.updateSettings, + [InteractiveWindowMessages.StartDebugging]: Execution.startDebugging, + [InteractiveWindowMessages.StopDebugging]: Execution.stopDebugging, + [InteractiveWindowMessages.ScrollToCell]: Effects.scrollToCell, + [InteractiveWindowMessages.UpdateKernel]: Kernel.updateStatus, + [SharedMessages.LocInit]: CommonEffects.handleLocInit }; diff --git a/src/datascience-ui/interactive-common/redux/postOffice.ts b/src/datascience-ui/interactive-common/redux/postOffice.ts index 1a7891eef9e3..a293d02557bd 100644 --- a/src/datascience-ui/interactive-common/redux/postOffice.ts +++ b/src/datascience-ui/interactive-common/redux/postOffice.ts @@ -4,113 +4,32 @@ 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 { PostOffice } from '../../react-common/postOffice'; -// Action types for Incoming messages. Basically all possible messages prefixed with the word 'action' -// This allows us to have a reducer for an incoming message and a separate reducer for an outgoing message. -// Note: Couldn't figure out a way to just generate this from the keys of the InteractiveWindowMessages. -// String literals can't come from a concat of another -export enum IncomingMessageActions { - // tslint:disable-next-line: prefer-template - STARTCELL = 'action.start_cell', - FINISHCELL = 'action.finish_cell', - UPDATECELL = 'action.update_cell', - GOTOCODECELL = 'action.gotocell_code', - COPYCODECELL = 'action.copycell_code', - RESTARTKERNEL = 'action.restart_kernel', - EXPORT = 'action.export_to_ipynb', - GETALLCELLS = 'action.get_all_cells', - RETURNALLCELLS = 'action.return_all_cells', - DELETECELL = 'action.delete_cell', - DELETEALLCELLS = 'action.delete_all_cells', - UNDO = 'action.undo', - REDO = 'action.redo', - EXPANDALL = 'action.expand_all', - COLLAPSEALL = 'action.collapse_all', - STARTPROGRESS = 'action.start_progress', - STOPPROGRESS = 'action.stop_progress', - INTERRUPT = 'action.interrupt', - SUBMITNEWCELL = 'action.submit_new_cell', - UPDATESETTINGS = 'action.update_settings', - DOSAVE = 'action.DoSave', - SENDINFO = 'action.send_info', - STARTED = 'action.started', - ADDEDSYSINFO = 'action.added_sys_info', - REMOTEADDCODE = 'action.remote_add_code', - REMOTEREEXECUTECODE = 'action.remote_reexecute_code', - ACTIVATE = 'action.activate', - SHOWDATAVIEWER = 'action.show_data_explorer', - GETVARIABLESREQUEST = 'ACTION.GET_VARIABLES_REQUEST', - GETVARIABLESRESPONSE = 'action.get_variables_response', - GETVARIABLEVALUEREQUEST = 'action.get_variable_value_request', - GETVARIABLEVALUERESPONSE = 'action.get_variable_value_response', - VARIABLEEXPLORERTOGGLE = 'action.variable_explorer_toggle', - PROVIDECOMPLETIONITEMSREQUEST = 'action.provide_completion_items_request', - CANCELCOMPLETIONITEMSREQUEST = 'action.cancel_completion_items_request', - PROVIDECOMPLETIONITEMSRESPONSE = 'action.provide_completion_items_response', - PROVIDEHOVERREQUEST = 'action.provide_hover_request', - CANCELHOVERREQUEST = 'action.cancel_hover_request', - PROVIDEHOVERRESPONSE = 'action.provide_hover_response', - PROVIDESIGNATUREHELPREQUEST = 'action.provide_signature_help_request', - CANCELSIGNATUREHELPREQUEST = 'action.cancel_signature_help_request', - PROVIDESIGNATUREHELPRESPONSE = 'action.provide_signature_help_response', - RESOLVECOMPLETIONITEMREQUEST = 'action.resolve_completion_item_request', - CANCELRESOLVECOMPLETIONITEMREQUEST = 'action.cancel_completion_items_request', - RESOLVECOMPLETIONITEMRESPONSE = 'action.resolve_completion_item_response', - ADDCELL = 'action.add_cell', - EDITCELL = 'action.edit_cell', - REMOVECELL = 'action.remove_cell', - SWAPCELLS = 'action.swap_cells', - INSERTCELL = 'action.insert_cell', - LOADONIGASMASSEMBLYREQUEST = 'action.load_onigasm_assembly_request', - LOADONIGASMASSEMBLYRESPONSE = 'action.load_onigasm_assembly_response', - LOADTMLANGUAGEREQUEST = 'action.load_tmlanguage_request', - LOADTMLANGUAGERESPONSE = 'action.load_tmlanguage_response', - OPENLINK = 'action.open_link', - SHOWPLOT = 'action.show_plot', - STARTDEBUGGING = 'action.start_debugging', - STOPDEBUGGING = 'action.stop_debugging', - GATHERCODE = 'action.gather_code', - LOADALLCELLS = 'action.load_all_cells', - LOADALLCELLSCOMPLETE = 'action.load_all_cells_complete', - SCROLLTOCELL = 'action.scroll_to_cell', - REEXECUTECELL = 'action.reexecute_cell', - NOTEBOOKIDENTITY = 'action.identity', - NOTEBOOKDIRTY = 'action.dirty', - NOTEBOOKCLEAN = 'action.clean', - SAVEALL = 'action.save_all', - NATIVECOMMAND = 'action.native_command', - VARIABLESCOMPLETE = 'action.variables_complete', - NOTEBOOKRUNALLCELLS = 'action.notebook_run_all_cells', - NOTEBOOKRUNSELECTEDCELL = 'action.notebook_run_selected_cell', - NOTEBOOKADDCELLBELOW = 'action.notebook_add_cell_below', - RENDERCOMPLETE = 'action.finished_rendering_cells', - FOCUSEDCELLEDITOR = 'action.focused_cell_editor', - MONACOREADY = 'action.monaco_ready', - GETCSSREQUEST = 'action.get_css_request', - GETCSSRESPONSE = 'action.get_css_response', - GETMONACOTHEMEREQUEST = 'action.get_monaco_theme_request', - GETMONACOTHEMERESPONSE = 'action.get_monaco_theme_response', - UPDATEKERNEL = 'action.update_kernel', - LOCINIT = 'action.loc_init' -} - export const AllowedMessages = [...Object.values(InteractiveWindowMessages), ...Object.values(CssMessages), ...Object.values(SharedMessages)]; // Actions created from messages export function createPostableAction(message: T, payload?: M[T]): Redux.AnyAction { - return { type: `${message}`, payload }; + const newPayload: BaseReduxActionPayload = ({ + data: payload, + messageDirection: 'outgoing' + // tslint:disable-next-line: no-any + } as any) as BaseReduxActionPayload; + return { type: `${message}`, payload: newPayload }; } export function generatePostOfficeSendReducer(postOffice: PostOffice): Redux.Reducer<{}, Redux.AnyAction> { // tslint:disable-next-line: no-function-expression return function(_state: {} | undefined, action: Redux.AnyAction): {} { // Make sure a valid message - if (AllowedMessages.find(k => k === action.type)) { + // tslint:disable-next-line: no-any + const payload: BaseReduxActionPayload<{}> | undefined = action.payload; + if (AllowedMessages.find(k => k === action.type) && payload?.messageDirection === 'outgoing') { // Just post this to the post office. // tslint:disable-next-line: no-any - postOffice.sendMessage(action.type, action.payload); + postOffice.sendMessage(action.type, payload.data as any); } // We don't modify the state. diff --git a/src/datascience-ui/interactive-common/redux/reducers/commonEffects.ts b/src/datascience-ui/interactive-common/redux/reducers/commonEffects.ts index 2cff42b522a3..a34452dcc870 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/commonEffects.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/commonEffects.ts @@ -7,52 +7,53 @@ import { IGetMonacoThemeResponse } from '../../../../client/datascience/monacoMe import { IMainState } from '../../../interactive-common/mainState'; import { Helpers } from '../../../interactive-common/redux/reducers/helpers'; import { storeLocStrings } from '../../../react-common/locReactSide'; -import { CommonReducerArg } from './types'; +import { CommonActionType, CommonReducerArg } from './types'; export namespace CommonEffects { - export function notebookDirty(arg: CommonReducerArg): IMainState { + export function notebookDirty(arg: CommonReducerArg): IMainState { return { ...arg.prevState, dirty: true }; } - export function notebookClean(arg: CommonReducerArg): IMainState { + export function notebookClean(arg: CommonReducerArg): IMainState { return { ...arg.prevState, dirty: false }; } - export function startProgress(arg: CommonReducerArg): IMainState { + export function startProgress(arg: CommonReducerArg): IMainState { return { ...arg.prevState, busy: true }; } - export function stopProgress(arg: CommonReducerArg): IMainState { + export function stopProgress(arg: CommonReducerArg): IMainState { return { ...arg.prevState, busy: false }; } - export function activate(arg: CommonReducerArg): IMainState { + export function activate(arg: CommonReducerArg): IMainState { return { ...arg.prevState, activateCount: arg.prevState.activateCount + 1 }; } - export function handleLocInit(arg: CommonReducerArg): IMainState { + export function handleLocInit(arg: CommonReducerArg): IMainState { // Read in the loc strings + console.error(arg.payload); const locJSON = JSON.parse(arg.payload.data); storeLocStrings(locJSON); return arg.prevState; } - export function handleCss(arg: CommonReducerArg): IMainState { + export function handleCss(arg: CommonReducerArg): IMainState { // Recompute our known dark value from the class name in the body // VS code should update this dynamically when the theme changes const computedKnownDark = Helpers.computeKnownDark(arg.prevState.settings); @@ -66,27 +67,27 @@ export namespace CommonEffects { let fontFamily: string = "Consolas, 'Courier New', monospace"; const sizeSetting = '--code-font-size: '; const familySetting = '--code-font-family: '; - const fontSizeIndex = arg.payload.css.indexOf(sizeSetting); - const fontFamilyIndex = arg.payload.css.indexOf(familySetting); + const fontSizeIndex = arg.payload.data.css.indexOf(sizeSetting); + const fontFamilyIndex = arg.payload.data.css.indexOf(familySetting); if (fontSizeIndex > -1) { - const fontSizeEndIndex = arg.payload.css.indexOf('px;', fontSizeIndex + sizeSetting.length); - fontSize = parseInt(arg.payload.css.substring(fontSizeIndex + sizeSetting.length, fontSizeEndIndex), 10); + const fontSizeEndIndex = arg.payload.data.css.indexOf('px;', fontSizeIndex + sizeSetting.length); + fontSize = parseInt(arg.payload.data.css.substring(fontSizeIndex + sizeSetting.length, fontSizeEndIndex), 10); } if (fontFamilyIndex > -1) { - const fontFamilyEndIndex = arg.payload.css.indexOf(';', fontFamilyIndex + familySetting.length); - fontFamily = arg.payload.css.substring(fontFamilyIndex + familySetting.length, fontFamilyEndIndex); + const fontFamilyEndIndex = arg.payload.data.css.indexOf(';', fontFamilyIndex + familySetting.length); + fontFamily = arg.payload.data.css.substring(fontFamilyIndex + familySetting.length, fontFamilyEndIndex); } return { ...arg.prevState, - rootCss: arg.payload.css, + rootCss: arg.payload.data.css, font: { size: fontSize, family: fontFamily }, - vscodeThemeName: arg.payload.theme, + vscodeThemeName: arg.payload.data.theme, knownDark: computedKnownDark, baseTheme: newBaseTheme }; diff --git a/src/datascience-ui/interactive-common/redux/reducers/helpers.ts b/src/datascience-ui/interactive-common/redux/reducers/helpers.ts index 8653be19a67c..d5205fe7639a 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/helpers.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/helpers.ts @@ -9,7 +9,7 @@ import { ICell, IDataScienceExtraSettings } from '../../../../client/datascience import { arePathsSame } from '../../../react-common/arePathsSame'; import { detectBaseTheme } from '../../../react-common/themeDetector'; import { ICellViewModel, IMainState } from '../../mainState'; -import { CommonReducerArg } from './types'; +import { CommonActionType, CommonReducerArg } from './types'; const StackLimit = 10; @@ -44,14 +44,14 @@ export namespace Helpers { return cvm as ICellViewModel; } - export function updateOrAdd(arg: CommonReducerArg, generateVM: (cell: ICell, mainState: IMainState) => ICellViewModel): IMainState { + export function updateOrAdd(arg: CommonReducerArg, generateVM: (cell: ICell, mainState: IMainState) => ICellViewModel): IMainState { // First compute new execution count. - const newExecutionCount = arg.payload.data.execution_count - ? Math.max(arg.prevState.currentExecutionCount, parseInt(arg.payload.data.execution_count.toString(), 10)) + const newExecutionCount = arg.payload.data.data.execution_count + ? Math.max(arg.prevState.currentExecutionCount, parseInt(arg.payload.data.data.execution_count.toString(), 10)) : arg.prevState.currentExecutionCount; const index = arg.prevState.cellVMs.findIndex((c: ICellViewModel) => { - return c.cell.id === arg.payload.id && c.cell.line === arg.payload.line && arePathsSame(c.cell.file, arg.payload.file); + return c.cell.id === arg.payload.data.id && c.cell.line === arg.payload.data.line && arePathsSame(c.cell.file, arg.payload.data.file); }); if (index >= 0) { // This means the cell existed already so it was actual executed code. @@ -71,9 +71,9 @@ export namespace Helpers { ...newVMs[index], cell: { ...newVMs[index].cell, - state: arg.payload.state, + state: arg.payload.data.state, data: { - ...arg.payload.data, + ...arg.payload.data.data, source: newVMs[index].cell.data.source } } @@ -87,7 +87,7 @@ export namespace Helpers { }; } else { // This is an entirely new cell (it may have started out as finished) - const newVM = generateVM(arg.payload, arg.prevState); + const newVM = generateVM(arg.payload.data, arg.prevState); const newVMs = [...arg.prevState.cellVMs, newVM]; return { ...arg.prevState, diff --git a/src/datascience-ui/interactive-common/redux/reducers/kernel.ts b/src/datascience-ui/interactive-common/redux/reducers/kernel.ts index 4c232516a5a2..7acface3c37a 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/kernel.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/kernel.ts @@ -5,20 +5,21 @@ import { InteractiveWindowMessages } from '../../../../client/datascience/intera import { CellState } from '../../../../client/datascience/types'; import { IMainState, IServerState } from '../../mainState'; import { createPostableAction } from '../postOffice'; -import { CommonReducerArg } from './types'; +import { CommonActionType, CommonReducerArg } from './types'; export namespace Kernel { - export function selectKernel(arg: CommonReducerArg): IMainState { + // tslint:disable-next-line: no-any + export function selectKernel(arg: CommonReducerArg): IMainState { arg.queueAction(createPostableAction(InteractiveWindowMessages.SelectKernel)); return arg.prevState; } - export function selectJupyterURI(arg: CommonReducerArg): IMainState { + export function selectJupyterURI(arg: CommonReducerArg): IMainState { arg.queueAction(createPostableAction(InteractiveWindowMessages.SelectJupyterServer)); return arg.prevState; } - export function restartKernel(arg: CommonReducerArg): IMainState { + export function restartKernel(arg: CommonReducerArg): IMainState { arg.queueAction(createPostableAction(InteractiveWindowMessages.RestartKernel)); // Set busy until kernel is restarted @@ -28,7 +29,7 @@ export namespace Kernel { }; } - export function interruptKernel(arg: CommonReducerArg): IMainState { + export function interruptKernel(arg: CommonReducerArg): IMainState { arg.queueAction(createPostableAction(InteractiveWindowMessages.Interrupt)); // Set busy until kernel is finished interrupting @@ -38,13 +39,13 @@ export namespace Kernel { }; } - export function updateStatus(arg: CommonReducerArg): IMainState { + export function updateStatus(arg: CommonReducerArg): IMainState { return { ...arg.prevState, kernel: { - localizedUri: arg.payload.localizedUri, - jupyterServerStatus: arg.payload.jupyterServerStatus, - displayName: arg.payload.displayName + localizedUri: arg.payload.data.localizedUri, + jupyterServerStatus: arg.payload.data.jupyterServerStatus, + displayName: arg.payload.data.displayName } }; } diff --git a/src/datascience-ui/interactive-common/redux/reducers/monaco.ts b/src/datascience-ui/interactive-common/redux/reducers/monaco.ts index e3c9b60e41c2..08d1558ed628 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/monaco.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/monaco.ts @@ -13,14 +13,14 @@ import { IResolveCompletionItemResponse } from '../../../../client/datascience/interactive-common/interactiveWindowTypes'; import { BaseReduxActionPayload } from '../../../../client/datascience/interactive-common/types'; +import { CssMessages } from '../../../../client/datascience/messages'; import { IGetMonacoThemeResponse } from '../../../../client/datascience/monacoMessages'; import { logMessage } from '../../../react-common/logger'; import { PostOffice } from '../../../react-common/postOffice'; import { combineReducers, QueuableAction, ReducerArg, ReducerFunc } from '../../../react-common/reduxUtils'; import { IntellisenseProvider } from '../../intellisenseProvider'; import { initializeTokenizer, registerMonacoLanguage } from '../../tokenizer'; -import { IncomingMessageActions } from '../postOffice'; -import { CommonActionType, ICodeCreatedAction, IEditCellAction, PrimitiveTypeInReduxActionPayload } from './types'; +import { CommonActionType, createIncomingAction, ICodeCreatedAction, IEditCellAction } from './types'; export interface IMonacoState { onigasmData: ArrayBuffer | undefined; @@ -30,19 +30,11 @@ export interface IMonacoState { postOffice: PostOffice; } -type MonacoReducerFunc = T extends never | undefined - ? ReducerFunc - : T extends PrimitiveTypeInReduxActionPayload - ? ReducerFunc - : ReducerFunc; +type MonacoReducerFunc = ReducerFunc>; -type MonacoReducerArg = T extends never | undefined - ? ReducerArg - : T extends PrimitiveTypeInReduxActionPayload - ? ReducerArg - : ReducerArg; +type MonacoReducerArg = ReducerArg>; -function handleStarted(arg: MonacoReducerArg): IMonacoState { +function handleStarted(arg: MonacoReducerArg): IMonacoState { // If in test mode, register the monaco provider if (arg.prevState.testMode) { registerMonacoLanguage(); @@ -70,7 +62,7 @@ function finishTokenizer(buffer: ArrayBuffer, tmJson: string, arg: MonacoRedu if (e) { logMessage(`ERROR from onigasm: ${e}`); } - arg.queueAction({ type: IncomingMessageActions.MONACOREADY }); + arg.queueAction(createIncomingAction(InteractiveWindowMessages.MonacoReady)); }).ignoreErrors(); } @@ -105,46 +97,46 @@ function handleLoadTmLanguageResponse(arg: MonacoReducerArg): IMonacoSta function handleThemeResponse(arg: MonacoReducerArg): IMonacoState { // Tell monaco we have a new theme. THis is like a state update for monaco - monacoEditor.editor.defineTheme(Identifiers.GeneratedThemeName, arg.payload.theme); + monacoEditor.editor.defineTheme(Identifiers.GeneratedThemeName, arg.payload.data.theme); return arg.prevState; } function handleCompletionItemsResponse(arg: MonacoReducerArg): IMonacoState { const ensuredProvider = handleStarted(arg); - ensuredProvider.intellisenseProvider!.handleCompletionResponse(arg.payload); + ensuredProvider.intellisenseProvider!.handleCompletionResponse(arg.payload.data); return ensuredProvider; } function handleResolveCompletionItemResponse(arg: MonacoReducerArg): IMonacoState { const ensuredProvider = handleStarted(arg); - ensuredProvider.intellisenseProvider!.handleResolveCompletionItemResponse(arg.payload); + ensuredProvider.intellisenseProvider!.handleResolveCompletionItemResponse(arg.payload.data); return ensuredProvider; } function handleSignatureHelpResponse(arg: MonacoReducerArg): IMonacoState { const ensuredProvider = handleStarted(arg); - ensuredProvider.intellisenseProvider!.handleSignatureHelpResponse(arg.payload); + ensuredProvider.intellisenseProvider!.handleSignatureHelpResponse(arg.payload.data); return ensuredProvider; } function handleHoverResponse(arg: MonacoReducerArg): IMonacoState { const ensuredProvider = handleStarted(arg); - ensuredProvider.intellisenseProvider!.handleHoverResponse(arg.payload); + ensuredProvider.intellisenseProvider!.handleHoverResponse(arg.payload.data); return ensuredProvider; } function handleCodeCreated(arg: MonacoReducerArg): IMonacoState { const ensuredProvider = handleStarted(arg); - if (arg.payload.cellId) { - ensuredProvider.intellisenseProvider!.mapCellIdToModelId(arg.payload.cellId, arg.payload.modelId); + if (arg.payload.data.cellId) { + ensuredProvider.intellisenseProvider!.mapCellIdToModelId(arg.payload.data.cellId, arg.payload.data.modelId); } return ensuredProvider; } function handleEditCell(arg: MonacoReducerArg): IMonacoState { const ensuredProvider = handleStarted(arg); - if (arg.payload.cellId) { - ensuredProvider.intellisenseProvider!.mapCellIdToModelId(arg.payload.cellId, arg.payload.modelId); + if (arg.payload.data.cellId) { + ensuredProvider.intellisenseProvider!.mapCellIdToModelId(arg.payload.data.cellId, arg.payload.data.modelId); } return ensuredProvider; } @@ -161,16 +153,21 @@ function handleUnmount(arg: MonacoReducerArg): IMonacoState { }; } +// type MonacoReducerFunctions = { +// [P in keyof T]: T[P] extends never | undefined ? MonacoReducerFunc : MonacoReducerFunc; +// }; + +// type IMonacoActionMapping = MonacoReducerFunctions & MonacoReducerFunctions; // Create a mapping between message and reducer type class IMonacoActionMapping { public [InteractiveWindowMessages.Started]: MonacoReducerFunc; - public [IncomingMessageActions.LOADONIGASMASSEMBLYRESPONSE]: MonacoReducerFunc; - public [IncomingMessageActions.LOADTMLANGUAGERESPONSE]: MonacoReducerFunc; - public [IncomingMessageActions.GETMONACOTHEMERESPONSE]: MonacoReducerFunc; - public [IncomingMessageActions.PROVIDECOMPLETIONITEMSRESPONSE]: MonacoReducerFunc; - public [IncomingMessageActions.PROVIDESIGNATUREHELPRESPONSE]: MonacoReducerFunc; - public [IncomingMessageActions.PROVIDEHOVERRESPONSE]: MonacoReducerFunc; - public [IncomingMessageActions.RESOLVECOMPLETIONITEMRESPONSE]: MonacoReducerFunc; + public [InteractiveWindowMessages.LoadOnigasmAssemblyResponse]: MonacoReducerFunc; + public [InteractiveWindowMessages.LoadTmLanguageResponse]: MonacoReducerFunc; + public [CssMessages.GetMonacoThemeResponse]: MonacoReducerFunc; + public [InteractiveWindowMessages.ProvideCompletionItemsResponse]: MonacoReducerFunc; + public [InteractiveWindowMessages.ProvideSignatureHelpResponse]: MonacoReducerFunc; + public [InteractiveWindowMessages.ProvideHoverResponse]: MonacoReducerFunc; + public [InteractiveWindowMessages.ResolveCompletionItemResponse]: MonacoReducerFunc; public [CommonActionType.CODE_CREATED]: MonacoReducerFunc; public [CommonActionType.EDIT_CELL]: MonacoReducerFunc; public [CommonActionType.UNMOUNT]: MonacoReducerFunc; @@ -179,13 +176,13 @@ class IMonacoActionMapping { // Create the map between message type and the actual function to call to update state const reducerMap: IMonacoActionMapping = { [InteractiveWindowMessages.Started]: handleStarted, - [IncomingMessageActions.LOADONIGASMASSEMBLYRESPONSE]: handleLoadOnigasmResponse, - [IncomingMessageActions.LOADTMLANGUAGERESPONSE]: handleLoadTmLanguageResponse, - [IncomingMessageActions.GETMONACOTHEMERESPONSE]: handleThemeResponse, - [IncomingMessageActions.PROVIDECOMPLETIONITEMSRESPONSE]: handleCompletionItemsResponse, - [IncomingMessageActions.PROVIDESIGNATUREHELPRESPONSE]: handleSignatureHelpResponse, - [IncomingMessageActions.PROVIDEHOVERRESPONSE]: handleHoverResponse, - [IncomingMessageActions.RESOLVECOMPLETIONITEMRESPONSE]: handleResolveCompletionItemResponse, + [InteractiveWindowMessages.LoadOnigasmAssemblyResponse]: handleLoadOnigasmResponse, + [InteractiveWindowMessages.LoadTmLanguageResponse]: handleLoadTmLanguageResponse, + [CssMessages.GetMonacoThemeResponse]: handleThemeResponse, + [InteractiveWindowMessages.ProvideCompletionItemsResponse]: handleCompletionItemsResponse, + [InteractiveWindowMessages.ProvideSignatureHelpResponse]: handleSignatureHelpResponse, + [InteractiveWindowMessages.ProvideHoverResponse]: handleHoverResponse, + [InteractiveWindowMessages.ResolveCompletionItemResponse]: handleResolveCompletionItemResponse, [CommonActionType.CODE_CREATED]: handleCodeCreated, [CommonActionType.EDIT_CELL]: handleEditCell, [CommonActionType.UNMOUNT]: handleUnmount diff --git a/src/datascience-ui/interactive-common/redux/reducers/transfer.ts b/src/datascience-ui/interactive-common/redux/reducers/transfer.ts index f12fd12b8d18..ce4f5f37dc52 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/transfer.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/transfer.ts @@ -6,11 +6,11 @@ import { CssMessages } from '../../../../client/datascience/messages'; import { extractInputText, IMainState } from '../../mainState'; import { createPostableAction } from '../postOffice'; import { Helpers } from './helpers'; -import { CommonReducerArg, ICellAction, IEditCellAction, ILinkClickAction, ISendCommandAction, IShowDataViewerAction, IShowPlotAction } from './types'; +import { CommonActionType, CommonReducerArg, ICellAction, IEditCellAction, ILinkClickAction, ISendCommandAction, IShowDataViewerAction } from './types'; // These are all reducers that don't actually change state. They merely dispatch a message to the other side. export namespace Transfer { - export function exportCells(arg: CommonReducerArg): IMainState { + export function exportCells(arg: CommonReducerArg): IMainState { const cellContents = arg.prevState.cellVMs.map(v => v.cell); arg.queueAction(createPostableAction(InteractiveWindowMessages.Export, cellContents)); @@ -21,7 +21,7 @@ export namespace Transfer { }; } - export function save(arg: CommonReducerArg): IMainState { + export function save(arg: CommonReducerArg): IMainState { // Note: this is assuming editor contents have already been saved. That should happen as a result of focus change // Actually waiting for save results before marking as not dirty, so don't do it here. @@ -29,47 +29,49 @@ export namespace Transfer { return arg.prevState; } - export function showDataViewer(arg: CommonReducerArg): IMainState { - arg.queueAction(createPostableAction(InteractiveWindowMessages.ShowDataViewer, { variable: arg.payload.variable, columnSize: arg.payload.columnSize })); + export function showDataViewer(arg: CommonReducerArg): IMainState { + arg.queueAction(createPostableAction(InteractiveWindowMessages.ShowDataViewer, { variable: arg.payload.data.variable, columnSize: arg.payload.data.columnSize })); return arg.prevState; } - export function sendCommand(arg: CommonReducerArg): IMainState { - arg.queueAction(createPostableAction(InteractiveWindowMessages.NativeCommand, { command: arg.payload.command, source: arg.payload.commandType })); + export function sendCommand(arg: CommonReducerArg): IMainState { + arg.queueAction(createPostableAction(InteractiveWindowMessages.NativeCommand, { command: arg.payload.data.command, source: arg.payload.data.commandType })); return arg.prevState; } - export function showPlot(arg: CommonReducerArg): IMainState { - arg.queueAction(createPostableAction(InteractiveWindowMessages.ShowPlot, arg.payload.imageHtml)); + export function showPlot(arg: CommonReducerArg): IMainState { + if (arg.payload.data) { + arg.queueAction(createPostableAction(InteractiveWindowMessages.ShowPlot, arg.payload.data)); + } return arg.prevState; } - export function linkClick(arg: CommonReducerArg): IMainState { - if (arg.payload.href.startsWith('data:image/png')) { - arg.queueAction(createPostableAction(InteractiveWindowMessages.SavePng, arg.payload.href)); + export function linkClick(arg: CommonReducerArg): IMainState { + if (arg.payload.data.href.startsWith('data:image/png')) { + arg.queueAction(createPostableAction(InteractiveWindowMessages.SavePng, arg.payload.data.href)); } else { - arg.queueAction(createPostableAction(InteractiveWindowMessages.OpenLink, arg.payload.href)); + arg.queueAction(createPostableAction(InteractiveWindowMessages.OpenLink, arg.payload.data.href)); } return arg.prevState; } - export function getAllCells(arg: CommonReducerArg): IMainState { + export function getAllCells(arg: CommonReducerArg): IMainState { const cells = arg.prevState.cellVMs.map(c => c.cell); arg.queueAction(createPostableAction(InteractiveWindowMessages.ReturnAllCells, cells)); return arg.prevState; } - export function gotoCell(arg: CommonReducerArg): IMainState { - const cellVM = arg.prevState.cellVMs.find(c => c.cell.id === arg.payload.cellId); + export function gotoCell(arg: CommonReducerArg): IMainState { + const cellVM = arg.prevState.cellVMs.find(c => c.cell.id === arg.payload.data.cellId); if (cellVM && cellVM.cell.data.cell_type === 'code') { arg.queueAction(createPostableAction(InteractiveWindowMessages.GotoCodeCell, { file: cellVM.cell.file, line: cellVM.cell.line })); } return arg.prevState; } - export function copyCellCode(arg: CommonReducerArg): IMainState { - let cellVM = arg.prevState.cellVMs.find(c => c.cell.id === arg.payload.cellId); - if (!cellVM && arg.prevState.editCellVM && arg.payload.cellId === arg.prevState.editCellVM.cell.id) { + export function copyCellCode(arg: CommonReducerArg): IMainState { + let cellVM = arg.prevState.cellVMs.find(c => c.cell.id === arg.payload.data.cellId); + if (!cellVM && arg.prevState.editCellVM && arg.payload.data.cellId === arg.prevState.editCellVM.cell.id) { cellVM = arg.prevState.editCellVM; } @@ -81,28 +83,28 @@ export namespace Transfer { return arg.prevState; } - export function gather(arg: CommonReducerArg): IMainState { - const cellVM = arg.prevState.cellVMs.find(c => c.cell.id === arg.payload.cellId); + export function gather(arg: CommonReducerArg): IMainState { + const cellVM = arg.prevState.cellVMs.find(c => c.cell.id === arg.payload.data.cellId); if (cellVM) { arg.queueAction(createPostableAction(InteractiveWindowMessages.GatherCodeRequest, cellVM.cell)); } return arg.prevState; } - export function editCell(arg: CommonReducerArg): IMainState { - if (arg.payload.cellId) { - arg.queueAction(createPostableAction(InteractiveWindowMessages.EditCell, { changes: arg.payload.changes, id: arg.payload.cellId })); + export function editCell(arg: CommonReducerArg): IMainState { + if (arg.payload.data.cellId) { + arg.queueAction(createPostableAction(InteractiveWindowMessages.EditCell, { changes: arg.payload.data.changes, id: arg.payload.data.cellId })); // Update the uncomitted text on the cell view model // We keep this saved here so we don't re-render and we put this code into the input / code data // when focus is lost - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); - if (index >= 0 && arg.prevState.focusedCellId === arg.payload.cellId) { + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); + if (index >= 0 && arg.prevState.focusedCellId === arg.payload.data.cellId) { const newVMs = [...arg.prevState.cellVMs]; const current = arg.prevState.cellVMs[index]; const newCell = { ...current, - uncomittedText: arg.payload.code + uncomittedText: arg.payload.data.code }; // tslint:disable-next-line: no-any @@ -116,7 +118,7 @@ export namespace Transfer { return arg.prevState; } - export function started(arg: CommonReducerArg): IMainState { + export function started(arg: CommonReducerArg): IMainState { // Send all of our initial requests arg.queueAction(createPostableAction(InteractiveWindowMessages.Started)); arg.queueAction(createPostableAction(CssMessages.GetCssRequest, { isDark: arg.prevState.baseTheme !== 'vscode-light' })); @@ -126,7 +128,7 @@ export namespace Transfer { return arg.prevState; } - export function loadedAllCells(arg: CommonReducerArg): IMainState { + export function loadedAllCells(arg: CommonReducerArg): IMainState { arg.queueAction(createPostableAction(InteractiveWindowMessages.LoadAllCellsComplete, { cells: arg.prevState.cellVMs.map(c => c.cell) })); return arg.prevState; } diff --git a/src/datascience-ui/interactive-common/redux/reducers/types.ts b/src/datascience-ui/interactive-common/redux/reducers/types.ts index bb37cdc248ed..373052bc9c63 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/types.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/types.ts @@ -3,14 +3,15 @@ 'use strict'; import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; -import { IShowDataViewer, NativeCommandType } from '../../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { InteractiveWindowMessages, IShowDataViewer, NativeCommandType } from '../../../../client/datascience/interactive-common/interactiveWindowTypes'; import { BaseReduxActionPayload } from '../../../../client/datascience/interactive-common/types'; +import { IJupyterVariablesRequest } from '../../../../client/datascience/types'; import { ActionWithPayload, ReducerArg } from '../../../react-common/reduxUtils'; import { CursorPos, IMainState } from '../../mainState'; /** * How to add a new state change: - * 1) Add a new action. to CommonActionType + * 1) Add a new to CommonActionType (preferably `InteractiveWindowMessages` - to keep messages in the same place). * 2) Add a new interface (or reuse 1 below) if the action takes any parameters (ex: ICellAction) * 3) Add a new actionCreator function (this is how you use it from a react control) to the * appropriate actionCreator list (one for native and one for interactive). @@ -25,13 +26,9 @@ export enum CommonActionType { ARROW_DOWN = 'action.arrow_down', ARROW_UP = 'action.arrow_up', CHANGE_CELL_TYPE = 'action.change_cell_type', - CLEAR_ALL_OUTPUTS = 'action.clear_all_outputs', CLICK_CELL = 'action.click_cell', CODE_CREATED = 'action.code_created', - COLLAPSE_ALL = 'action.collapse_all', COPY_CELL_CODE = 'action.copy_cell_code', - DELETE_ALL_CELLS = 'action.delete_all_cells', - DELETE_CELL = 'action.delete_cell', DESELECT_CELL = 'action.deselect_cell', DOUBLE_CLICK_CELL = 'action.double_click_cell', EDITOR_LOADED = 'action.editor_loaded', @@ -40,7 +37,6 @@ export enum CommonActionType { EXECUTE_ALL_CELLS = 'action.execute_all_cells', EXECUTE_CELL = 'action.execute_cell', EXECUTE_CELL_AND_BELOW = 'action.execute_cell_and_below', - EXPAND_ALL = 'action.expand_all', EXPORT = 'action.export', FOCUS_CELL = 'action.focus_cell', GATHER_CELL = 'action.gather_cell', @@ -54,49 +50,78 @@ export enum CommonActionType { LINK_CLICK = 'action.link_click', MOVE_CELL_DOWN = 'action.move_cell_down', MOVE_CELL_UP = 'action.move_cell_up', - REDO = 'action.redo', REFRESH_VARIABLES = 'action.refresh_variables', RESTART_KERNEL = 'action.restart_kernel_action', SAVE = 'action.save', SCROLL = 'action.scroll', SELECT_CELL = 'action.select_cell', - SELECT_KERNEL = 'action.select_kernel', SELECT_SERVER = 'action.select_server', SEND_COMMAND = 'action.send_command', SHOW_DATA_VIEWER = 'action.show_data_viewer', - SHOW_PLOT = 'action.show_plot', - START_CELL = 'action.start_cell', SUBMIT_INPUT = 'action.submit_input', TOGGLE_INPUT_BLOCK = 'action.toggle_input_block', TOGGLE_LINE_NUMBERS = 'action.toggle_line_numbers', TOGGLE_OUTPUT = 'action.toggle_output', TOGGLE_VARIABLE_EXPLORER = 'action.toggle_variable_explorer', - UNDO = 'action.undo', UNFOCUS_CELL = 'action.unfocus_cell', UNMOUNT = 'action.unmount' } +export type CommonActionTypeMapping = { + [CommonActionType.INSERT_ABOVE]: ICellAction & IAddCellAction; + [CommonActionType.INSERT_BELOW]: ICellAction & IAddCellAction; + [CommonActionType.INSERT_ABOVE_FIRST]: IAddCellAction; + [CommonActionType.FOCUS_CELL]: ICellAndCursorAction; + [CommonActionType.UNFOCUS_CELL]: ICodeAction; + [CommonActionType.ADD_NEW_CELL]: IAddCellAction; + [CommonActionType.EDIT_CELL]: IEditCellAction; + [CommonActionType.EXECUTE_CELL]: IExecuteAction; + [CommonActionType.EXECUTE_ALL_CELLS]: never | undefined; + [CommonActionType.EXECUTE_ABOVE]: ICellAction; + [CommonActionType.EXECUTE_CELL_AND_BELOW]: ICodeAction; + [CommonActionType.RESTART_KERNEL]: never | undefined; + [CommonActionType.INTERRUPT_KERNEL]: never | undefined; + [CommonActionType.EXPORT]: never | undefined; + [CommonActionType.SAVE]: never | undefined; + [CommonActionType.SHOW_DATA_VIEWER]: IShowDataViewerAction; + [CommonActionType.SEND_COMMAND]: ISendCommandAction; + [CommonActionType.SELECT_CELL]: ICellAndCursorAction; + [CommonActionType.MOVE_CELL_UP]: ICellAction; + [CommonActionType.MOVE_CELL_DOWN]: ICellAction; + [CommonActionType.TOGGLE_LINE_NUMBERS]: ICellAction; + [CommonActionType.TOGGLE_OUTPUT]: ICellAction; + [CommonActionType.ARROW_UP]: ICodeAction; + [CommonActionType.ARROW_DOWN]: ICodeAction; + [CommonActionType.CHANGE_CELL_TYPE]: IChangeCellTypeAction; + [CommonActionType.LINK_CLICK]: ILinkClickAction; + [CommonActionType.GOTO_CELL]: ICellAction; + [CommonActionType.TOGGLE_INPUT_BLOCK]: ICellAction; + [CommonActionType.SUBMIT_INPUT]: ICodeAction; + [CommonActionType.SCROLL]: IScrollAction; + [CommonActionType.CLICK_CELL]: ICellAction; + [CommonActionType.COPY_CELL_CODE]: ICellAction; + [CommonActionType.GATHER_CELL]: ICellAction; + [CommonActionType.EDITOR_LOADED]: never | undefined; + [CommonActionType.LOADED_ALL_CELLS]: never | undefined; + [CommonActionType.UNMOUNT]: never | undefined; + [CommonActionType.SELECT_SERVER]: never | undefined; + [CommonActionType.CODE_CREATED]: ICodeCreatedAction; + [CommonActionType.GET_VARIABLE_DATA]: IJupyterVariablesRequest; + [CommonActionType.TOGGLE_VARIABLE_EXPLORER]: never | undefined; +}; + export interface IShowDataViewerAction extends IShowDataViewer {} export interface ILinkClickAction { href: string; } -export interface IShowPlotAction { - imageHtml: string; -} - export interface IScrollAction { isAtBottom: boolean; } // tslint:disable-next-line: no-any -export type PrimitiveTypeInReduxActionPayload = string | number | boolean | Buffer | any[]; -export type CommonReducerArg = T extends never | undefined - ? ReducerArg - : T extends PrimitiveTypeInReduxActionPayload - ? ReducerArg - : ReducerArg; +export type CommonReducerArg = ReducerArg>; export interface ICellAction { cellId: string | undefined; @@ -153,4 +178,12 @@ export interface IChangeCellTypeAction { cellId: string; currentCode: string; } -export type CommonAction = ActionWithPayload; +export type CommonAction = ActionWithPayload; + +export function createIncomingActionWithPayload(type: CommonActionType | InteractiveWindowMessages, data: T): CommonAction { + // tslint:disable-next-line: no-any + return { type, payload: ({ data, messageDirection: 'incoming' } as any) as BaseReduxActionPayload }; +} +export function createIncomingAction(type: CommonActionType | InteractiveWindowMessages): CommonAction { + return { type, payload: { messageDirection: 'incoming', data: undefined } }; +} diff --git a/src/datascience-ui/interactive-common/redux/reducers/variables.ts b/src/datascience-ui/interactive-common/redux/reducers/variables.ts index fb50f749fbea..6f51205a2d85 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/variables.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/variables.ts @@ -2,12 +2,12 @@ // Licensed under the MIT License. 'use strict'; import { Reducer } from 'redux'; -import { InteractiveWindowMessages } from '../../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { IInteractiveWindowMapping, InteractiveWindowMessages } from '../../../../client/datascience/interactive-common/interactiveWindowTypes'; import { BaseReduxActionPayload } from '../../../../client/datascience/interactive-common/types'; import { ICell, IJupyterVariable, IJupyterVariablesRequest, IJupyterVariablesResponse } from '../../../../client/datascience/types'; import { combineReducers, QueuableAction, ReducerArg, ReducerFunc } from '../../../react-common/reduxUtils'; -import { createPostableAction, IncomingMessageActions } from '../postOffice'; -import { CommonActionType, PrimitiveTypeInReduxActionPayload } from './types'; +import { createPostableAction } from '../postOffice'; +import { CommonActionType, CommonActionTypeMapping } from './types'; export type IVariableState = { currentExecutionCount: number; @@ -18,32 +18,23 @@ export type IVariableState = { pageSize: number; }; -type VariableReducerFunc = T extends never | undefined - ? ReducerFunc - : T extends PrimitiveTypeInReduxActionPayload - ? ReducerFunc - : ReducerFunc; - -type VariableReducerArg = T extends never | undefined - ? ReducerArg - : T extends PrimitiveTypeInReduxActionPayload - ? ReducerArg - : ReducerArg; +type VariableReducerFunc = ReducerFunc>; +type VariableReducerArg = ReducerArg>; function handleRequest(arg: VariableReducerArg): IVariableState { - const newExecutionCount = arg.payload.executionCount ? arg.payload.executionCount : arg.prevState.currentExecutionCount; + const newExecutionCount = arg.payload.data.executionCount ? arg.payload.data.executionCount : arg.prevState.currentExecutionCount; arg.queueAction( createPostableAction(InteractiveWindowMessages.GetVariablesRequest, { executionCount: newExecutionCount, - sortColumn: arg.payload.sortColumn, - startIndex: arg.payload.startIndex, - sortAscending: arg.payload.sortAscending, - pageSize: arg.payload.pageSize + sortColumn: arg.payload.data.sortColumn, + startIndex: arg.payload.data.startIndex, + sortAscending: arg.payload.data.sortAscending, + pageSize: arg.payload.data.pageSize }) ); return { ...arg.prevState, - pageSize: Math.max(arg.prevState.pageSize, arg.payload.pageSize) + pageSize: Math.max(arg.prevState.pageSize, arg.payload.data.pageSize) }; } @@ -60,7 +51,10 @@ function toggleVariableExplorer(arg: VariableReducerArg): IVariableState { return handleRequest({ ...arg, prevState: newState, - payload: { executionCount: arg.prevState.currentExecutionCount, sortColumn: 'name', sortAscending: true, startIndex: 0, pageSize: arg.prevState.pageSize } + payload: { + ...arg.payload, + data: { executionCount: arg.prevState.currentExecutionCount, sortColumn: 'name', sortAscending: true, startIndex: 0, pageSize: arg.prevState.pageSize } + } }); } else { return newState; @@ -68,7 +62,7 @@ function toggleVariableExplorer(arg: VariableReducerArg): IVariableState { } function handleResponse(arg: VariableReducerArg): IVariableState { - const response = arg.payload; + const response = arg.payload.data; // Check to see if we have moved to a new execution count if ( @@ -117,17 +111,23 @@ function handleResponse(arg: VariableReducerArg): IVa function handleRestarted(arg: VariableReducerArg): IVariableState { // If the variables are visible, refresh them if (arg.prevState.visible) { - return handleRequest({ ...arg, payload: { executionCount: 0, sortColumn: 'name', sortAscending: true, startIndex: 0, pageSize: arg.prevState.pageSize } }); + return handleRequest({ + ...arg, + payload: { ...arg.payload, data: { executionCount: 0, sortColumn: 'name', sortAscending: true, startIndex: 0, pageSize: arg.prevState.pageSize } } + }); } return arg.prevState; } function handleFinishCell(arg: VariableReducerArg): IVariableState { - const executionCount = arg.payload.data.execution_count ? parseInt(arg.payload.data.execution_count.toString(), 10) : undefined; + const executionCount = arg.payload.data.data.execution_count ? parseInt(arg.payload.data.data.execution_count.toString(), 10) : undefined; // If the variables are visible, refresh them if (arg.prevState.visible && executionCount) { - return handleRequest({ ...arg, payload: { executionCount, sortColumn: 'name', sortAscending: true, startIndex: 0, pageSize: arg.prevState.pageSize } }); + return handleRequest({ + ...arg, + payload: { ...arg.payload, data: { executionCount, sortColumn: 'name', sortAscending: true, startIndex: 0, pageSize: arg.prevState.pageSize } } + }); } return { ...arg.prevState, @@ -135,25 +135,22 @@ function handleFinishCell(arg: VariableReducerArg): IVariableState { }; } -// Create a mapping between message and reducer type -class IVariableActionMapping { - public [IncomingMessageActions.RESTARTKERNEL]: VariableReducerFunc; - public [IncomingMessageActions.FINISHCELL]: VariableReducerFunc; - public [CommonActionType.TOGGLE_VARIABLE_EXPLORER]: VariableReducerFunc; - public [CommonActionType.GET_VARIABLE_DATA]: VariableReducerFunc; - public [IncomingMessageActions.GETVARIABLESRESPONSE]: VariableReducerFunc; -} +type VariableReducerFunctions = { + [P in keyof T]: T[P] extends never | undefined ? VariableReducerFunc : VariableReducerFunc; +}; + +type VariableActionMapping = VariableReducerFunctions & VariableReducerFunctions; // Create the map between message type and the actual function to call to update state -const reducerMap: IVariableActionMapping = { - [IncomingMessageActions.RESTARTKERNEL]: handleRestarted, - [IncomingMessageActions.FINISHCELL]: handleFinishCell, +const reducerMap: Partial = { + [InteractiveWindowMessages.RestartKernel]: handleRestarted, + [InteractiveWindowMessages.FinishCell]: handleFinishCell, [CommonActionType.TOGGLE_VARIABLE_EXPLORER]: toggleVariableExplorer, [CommonActionType.GET_VARIABLE_DATA]: handleRequest, - [IncomingMessageActions.GETVARIABLESRESPONSE]: handleResponse + [InteractiveWindowMessages.GetVariablesResponse]: handleResponse }; -export function generateVariableReducer(): Reducer> { +export function generateVariableReducer(): Reducer>> { // First create our default state. const defaultState: IVariableState = { currentExecutionCount: 0, @@ -165,5 +162,5 @@ export function generateVariableReducer(): Reducer(defaultState, reducerMap); + return combineReducers>(defaultState, reducerMap); } diff --git a/src/datascience-ui/interactive-common/redux/store.ts b/src/datascience-ui/interactive-common/redux/store.ts index c547d81437a3..5d6bd5a7a73a 100644 --- a/src/datascience-ui/interactive-common/redux/store.ts +++ b/src/datascience-ui/interactive-common/redux/store.ts @@ -6,6 +6,8 @@ import * as Redux from 'redux'; import { createLogger } from 'redux-logger'; import { Identifiers } from '../../../client/datascience/constants'; import { InteractiveWindowMessages } from '../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { BaseReduxActionPayload } from '../../../client/datascience/interactive-common/types'; +import { CssMessages } from '../../../client/datascience/messages'; import { CellState } from '../../../client/datascience/types'; import { IMainState, ServerStatus } from '../../interactive-common/mainState'; import { getLocString } from '../../react-common/locReactSide'; @@ -14,7 +16,7 @@ import { combineReducers, createQueueableActionMiddleware, QueuableAction } from import { computeEditorOptions, getDefaultSettings } from '../../react-common/settingsReactSide'; import { createEditableCellVM, generateTestState } from '../mainState'; import { forceLoad } from '../transforms'; -import { AllowedMessages, createPostableAction, generatePostOfficeSendReducer, IncomingMessageActions } from './postOffice'; +import { AllowedMessages, createPostableAction, generatePostOfficeSendReducer } from './postOffice'; import { generateMonacoReducer, IMonacoState } from './reducers/monaco'; import { generateVariableReducer, IVariableState } from './reducers/variables'; @@ -167,7 +169,7 @@ function createMiddleWare(testMode: boolean): Redux.Middleware<{}, IStore>[] { // Create the logger if we're not in production mode or we're forcing logging const reduceLogMessage = ''; - const actionsWithLargePayload = [IncomingMessageActions.LOADONIGASMASSEMBLYRESPONSE, IncomingMessageActions.GETCSSRESPONSE, IncomingMessageActions.LOADTMLANGUAGERESPONSE]; + const actionsWithLargePayload = [InteractiveWindowMessages.LoadOnigasmAssemblyResponse, CssMessages.GetCssResponse, InteractiveWindowMessages.LoadTmLanguageResponse]; const logger = createLogger({ // tslint:disable-next-line: no-any stateTransformer: (state: any) => { @@ -262,13 +264,22 @@ export function createStore(skipDefault: boolean, baseTheme: string, testMode // turn them into actions. postOffice.addHandler({ // tslint:disable-next-line: no-any - handleMessage(message: string, payload: any): boolean { + handleMessage(message: string, payload?: any): boolean { // Double check this is one of our messages. React will actually post messages here too during development - if (AllowedMessages.find(k => k === message)) { - // Prefix message type with 'action.' so that we can: - // - Have one reducer for incoming - // - Have another reducer for outgoing - store.dispatch({ type: `action.${message}`, payload }); + if (!AllowedMessages.find(k => k === message)) { + return true; + } + // Add `isIncomingMessage` property so we can differentiate between messages in reducers. + // This way we: + // - Have one reducer for incoming + // - Have another reducer for outgoing + let basePayload = payload as BaseReduxActionPayload<{}> | undefined; + if (!basePayload?.broadcastReason && !basePayload?.messageDirection) { + // Re-wrap to indicate this is an incoming message. + basePayload = { data: payload, messageDirection: 'incoming' }; + } + if (AllowedMessages.find(k => k === message) && basePayload.messageDirection !== 'outgoing') { + store.dispatch({ type: message, payload: basePayload }); } return true; } diff --git a/src/datascience-ui/native-editor/redux/actions.ts b/src/datascience-ui/native-editor/redux/actions.ts index ad2618b4fb7c..16a38da4af97 100644 --- a/src/datascience-ui/native-editor/redux/actions.ts +++ b/src/datascience-ui/native-editor/redux/actions.ts @@ -3,12 +3,14 @@ 'use strict'; import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; import * as uuid from 'uuid/v4'; -import { NativeCommandType } from '../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { InteractiveWindowMessages, NativeCommandType } from '../../../client/datascience/interactive-common/interactiveWindowTypes'; import { IJupyterVariable, IJupyterVariablesRequest } from '../../../client/datascience/types'; import { CursorPos } from '../../interactive-common/mainState'; import { CommonAction, CommonActionType, + createIncomingAction, + createIncomingActionWithPayload, IAddCellAction, ICellAction, ICellAndCursorAction, @@ -20,81 +22,67 @@ import { ILinkClickAction, IRefreshVariablesAction, ISendCommandAction, - IShowDataViewerAction, - IShowPlotAction + IShowDataViewerAction } from '../../interactive-common/redux/reducers/types'; // See https://react-redux.js.org/using-react-redux/connect-mapdispatch#defining-mapdispatchtoprops-as-an-object export const actionCreators = { - insertAbove: (cellId: string | undefined): CommonAction => ({ type: CommonActionType.INSERT_ABOVE, payload: { cellId, newCellId: uuid() } }), - insertAboveFirst: (): CommonAction => ({ type: CommonActionType.INSERT_ABOVE_FIRST, payload: { newCellId: uuid() } }), - insertBelow: (cellId: string | undefined): CommonAction => ({ type: CommonActionType.INSERT_BELOW, payload: { cellId, newCellId: uuid() } }), - focusCell: (cellId: string, cursorPos: CursorPos = CursorPos.Current): CommonAction => ({ - type: CommonActionType.FOCUS_CELL, - payload: { cellId, cursorPos } - }), - unfocusCell: (cellId: string, code: string): CommonAction => ({ type: CommonActionType.UNFOCUS_CELL, payload: { cellId, code } }), - selectCell: (cellId: string, cursorPos: CursorPos = CursorPos.Current): CommonAction => ({ - type: CommonActionType.SELECT_CELL, - payload: { cellId, cursorPos } - }), - addCell: (): CommonAction => ({ type: CommonActionType.ADD_NEW_CELL, payload: { newCellId: uuid() } }), + insertAbove: (cellId: string | undefined): CommonAction => + createIncomingActionWithPayload(CommonActionType.INSERT_ABOVE, { cellId, newCellId: uuid() }), + insertAboveFirst: (): CommonAction => createIncomingActionWithPayload(CommonActionType.INSERT_ABOVE_FIRST, { newCellId: uuid() }), + insertBelow: (cellId: string | undefined): CommonAction => + createIncomingActionWithPayload(CommonActionType.INSERT_BELOW, { cellId, newCellId: uuid() }), + focusCell: (cellId: string, cursorPos: CursorPos = CursorPos.Current): CommonAction => + createIncomingActionWithPayload(CommonActionType.FOCUS_CELL, { cellId, cursorPos }), + unfocusCell: (cellId: string, code: string): CommonAction => createIncomingActionWithPayload(CommonActionType.UNFOCUS_CELL, { cellId, code }), + selectCell: (cellId: string, cursorPos: CursorPos = CursorPos.Current): CommonAction => + createIncomingActionWithPayload(CommonActionType.SELECT_CELL, { cellId, cursorPos }), + addCell: (): CommonAction => createIncomingActionWithPayload(CommonActionType.ADD_NEW_CELL, { newCellId: uuid() }), executeCell: (cellId: string, code: string, moveOp: 'add' | 'select' | 'none'): CommonAction => { if (moveOp === 'add') { - return { - type: CommonActionType.EXECUTE_CELL, - payload: { cellId, code, moveOp, newCellId: uuid() } - }; + return createIncomingActionWithPayload(CommonActionType.EXECUTE_CELL, { cellId, code, moveOp, newCellId: uuid() }); } else { - return { - type: CommonActionType.EXECUTE_CELL, - payload: { cellId, code, moveOp } - }; + return createIncomingActionWithPayload(CommonActionType.EXECUTE_CELL, { cellId, code, moveOp }); } }, - executeAllCells: (): CommonAction => ({ type: CommonActionType.EXECUTE_ALL_CELLS }), - executeAbove: (cellId: string): CommonAction => ({ type: CommonActionType.EXECUTE_ABOVE, payload: { cellId } }), - executeCellAndBelow: (cellId: string, code: string): CommonAction => ({ type: CommonActionType.EXECUTE_CELL_AND_BELOW, payload: { cellId, code } }), - toggleVariableExplorer: (): CommonAction => ({ type: CommonActionType.TOGGLE_VARIABLE_EXPLORER }), - refreshVariables: (newExecutionCount?: number): CommonAction => ({ type: CommonActionType.REFRESH_VARIABLES, payload: { newExecutionCount } }), - restartKernel: (): CommonAction => ({ type: CommonActionType.RESTART_KERNEL }), - interruptKernel: (): CommonAction => ({ type: CommonActionType.INTERRUPT_KERNEL }), - clearAllOutputs: (): CommonAction => ({ type: CommonActionType.CLEAR_ALL_OUTPUTS }), - export: (): CommonAction => ({ type: CommonActionType.EXPORT }), - save: (): CommonAction => ({ type: CommonActionType.SAVE }), - showDataViewer: (variable: IJupyterVariable, columnSize: number): CommonAction => ({ - type: CommonActionType.SHOW_DATA_VIEWER, - payload: { variable, columnSize } - }), - sendCommand: (command: NativeCommandType, commandType: 'mouse' | 'keyboard'): CommonAction => ({ - type: CommonActionType.SEND_COMMAND, - payload: { command, commandType } - }), - moveCellUp: (cellId: string): CommonAction => ({ type: CommonActionType.MOVE_CELL_UP, payload: { cellId } }), - moveCellDown: (cellId: string): CommonAction => ({ type: CommonActionType.MOVE_CELL_DOWN, payload: { cellId } }), - changeCellType: (cellId: string, currentCode: string): CommonAction => ({ type: CommonActionType.CHANGE_CELL_TYPE, payload: { cellId, currentCode } }), - toggleLineNumbers: (cellId: string): CommonAction => ({ type: CommonActionType.TOGGLE_LINE_NUMBERS, payload: { cellId } }), - toggleOutput: (cellId: string): CommonAction => ({ type: CommonActionType.TOGGLE_OUTPUT, payload: { cellId } }), - deleteCell: (cellId: string): CommonAction => ({ type: CommonActionType.DELETE_CELL, payload: { cellId } }), - undo: (): CommonAction => ({ type: CommonActionType.UNDO }), - redo: (): CommonAction => ({ type: CommonActionType.REDO }), - arrowUp: (cellId: string, code: string): CommonAction => ({ type: CommonActionType.ARROW_UP, payload: { cellId, code } }), - arrowDown: (cellId: string, code: string): CommonAction => ({ type: CommonActionType.ARROW_DOWN, payload: { cellId, code } }), - editCell: (cellId: string, changes: monacoEditor.editor.IModelContentChange[], modelId: string, code: string): CommonAction => ({ - type: CommonActionType.EDIT_CELL, - payload: { cellId, changes, modelId, code } - }), - linkClick: (href: string): CommonAction => ({ type: CommonActionType.LINK_CLICK, payload: { href } }), - showPlot: (imageHtml: string): CommonAction => ({ type: CommonActionType.SHOW_PLOT, payload: { imageHtml } }), - gatherCell: (cellId: string | undefined): CommonAction => ({ type: CommonActionType.GATHER_CELL, payload: { cellId } }), - editorLoaded: (): CommonAction => ({ type: CommonActionType.EDITOR_LOADED }), - codeCreated: (cellId: string | undefined, modelId: string): CommonAction => ({ type: CommonActionType.CODE_CREATED, payload: { cellId, modelId } }), - loadedAllCells: (): CommonAction => ({ type: CommonActionType.LOADED_ALL_CELLS }), - editorUnmounted: (): CommonAction => ({ type: CommonActionType.UNMOUNT }), - selectKernel: (): CommonAction => ({ type: CommonActionType.SELECT_KERNEL }), - selectServer: (): CommonAction => ({ type: CommonActionType.SELECT_SERVER }), - getVariableData: (newExecutionCount: number, startIndex: number = 0, pageSize: number = 100): CommonAction => ({ - type: CommonActionType.GET_VARIABLE_DATA, - payload: { executionCount: newExecutionCount, sortColumn: 'name', sortAscending: true, startIndex, pageSize } - }) + executeAllCells: (): CommonAction => createIncomingAction(CommonActionType.EXECUTE_ALL_CELLS), + executeAbove: (cellId: string): CommonAction => createIncomingActionWithPayload(CommonActionType.EXECUTE_ABOVE, { cellId }), + executeCellAndBelow: (cellId: string, code: string): CommonAction => createIncomingActionWithPayload(CommonActionType.EXECUTE_CELL_AND_BELOW, { cellId, code }), + toggleVariableExplorer: (): CommonAction => createIncomingAction(CommonActionType.TOGGLE_VARIABLE_EXPLORER), + refreshVariables: (newExecutionCount?: number): CommonAction => + createIncomingActionWithPayload(CommonActionType.REFRESH_VARIABLES, { newExecutionCount }), + restartKernel: (): CommonAction => createIncomingAction(CommonActionType.RESTART_KERNEL), + interruptKernel: (): CommonAction => createIncomingAction(CommonActionType.INTERRUPT_KERNEL), + clearAllOutputs: (): CommonAction => createIncomingAction(InteractiveWindowMessages.ClearAllOutputs), + export: (): CommonAction => createIncomingAction(CommonActionType.EXPORT), + save: (): CommonAction => createIncomingAction(CommonActionType.SAVE), + showDataViewer: (variable: IJupyterVariable, columnSize: number): CommonAction => + createIncomingActionWithPayload(CommonActionType.SHOW_DATA_VIEWER, { variable, columnSize }), + sendCommand: (command: NativeCommandType, commandType: 'mouse' | 'keyboard'): CommonAction => + createIncomingActionWithPayload(CommonActionType.SEND_COMMAND, { command, commandType }), + moveCellUp: (cellId: string): CommonAction => createIncomingActionWithPayload(CommonActionType.MOVE_CELL_UP, { cellId }), + moveCellDown: (cellId: string): CommonAction => createIncomingActionWithPayload(CommonActionType.MOVE_CELL_DOWN, { cellId }), + changeCellType: (cellId: string, currentCode: string): CommonAction => + createIncomingActionWithPayload(CommonActionType.CHANGE_CELL_TYPE, { cellId, currentCode }), + toggleLineNumbers: (cellId: string): CommonAction => createIncomingActionWithPayload(CommonActionType.TOGGLE_LINE_NUMBERS, { cellId }), + toggleOutput: (cellId: string): CommonAction => createIncomingActionWithPayload(CommonActionType.TOGGLE_OUTPUT, { cellId }), + deleteCell: (cellId: string): CommonAction => createIncomingActionWithPayload(InteractiveWindowMessages.DeleteCell, { cellId }), + undo: (): CommonAction => createIncomingAction(InteractiveWindowMessages.Undo), + redo: (): CommonAction => createIncomingAction(InteractiveWindowMessages.Redo), + arrowUp: (cellId: string, code: string): CommonAction => createIncomingActionWithPayload(CommonActionType.ARROW_UP, { cellId, code }), + arrowDown: (cellId: string, code: string): CommonAction => createIncomingActionWithPayload(CommonActionType.ARROW_DOWN, { cellId, code }), + editCell: (cellId: string, changes: monacoEditor.editor.IModelContentChange[], modelId: string, code: string): CommonAction => + createIncomingActionWithPayload(CommonActionType.EDIT_CELL, { cellId, changes, modelId, code }), + linkClick: (href: string): CommonAction => createIncomingActionWithPayload(CommonActionType.LINK_CLICK, { href }), + showPlot: (imageHtml: string): CommonAction => createIncomingActionWithPayload(InteractiveWindowMessages.ShowPlot, imageHtml), + gatherCell: (cellId: string | undefined): CommonAction => createIncomingActionWithPayload(CommonActionType.GATHER_CELL, { cellId }), + editorLoaded: (): CommonAction => createIncomingAction(CommonActionType.EDITOR_LOADED), + codeCreated: (cellId: string | undefined, modelId: string): CommonAction => + createIncomingActionWithPayload(CommonActionType.CODE_CREATED, { cellId, modelId }), + loadedAllCells: (): CommonAction => createIncomingAction(CommonActionType.LOADED_ALL_CELLS), + editorUnmounted: (): CommonAction => createIncomingAction(CommonActionType.UNMOUNT), + selectKernel: (): CommonAction => createIncomingAction(InteractiveWindowMessages.SelectKernel), + selectServer: (): CommonAction => createIncomingAction(CommonActionType.SELECT_SERVER), + getVariableData: (newExecutionCount: number, startIndex: number = 0, pageSize: number = 100): CommonAction => + createIncomingActionWithPayload(CommonActionType.GET_VARIABLE_DATA, { executionCount: newExecutionCount, sortColumn: 'name', sortAscending: true, startIndex, pageSize }) }; diff --git a/src/datascience-ui/native-editor/redux/mapping.ts b/src/datascience-ui/native-editor/redux/mapping.ts index 4e080a6ff9d6..46a023ad9ec9 100644 --- a/src/datascience-ui/native-editor/redux/mapping.ts +++ b/src/datascience-ui/native-editor/redux/mapping.ts @@ -1,103 +1,18 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. 'use strict'; -import { ILoadAllCells } from '../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { IInteractiveWindowMapping, InteractiveWindowMessages } from '../../../client/datascience/interactive-common/interactiveWindowTypes'; import { BaseReduxActionPayload } from '../../../client/datascience/interactive-common/types'; -import { IGetCssResponse } from '../../../client/datascience/messages'; -import { IGetMonacoThemeResponse } from '../../../client/datascience/monacoMessages'; -import { ICell } from '../../../client/datascience/types'; -import { IMainState, IServerState } from '../../interactive-common/mainState'; -import { IncomingMessageActions } from '../../interactive-common/redux/postOffice'; -import { - CommonActionType, - IAddCellAction, - ICellAction, - ICellAndCursorAction, - IChangeCellTypeAction, - ICodeAction, - IEditCellAction, - IExecuteAction, - ILinkClickAction, - ISendCommandAction, - IShowDataViewerAction, - IShowPlotAction, - PrimitiveTypeInReduxActionPayload -} from '../../interactive-common/redux/reducers/types'; +import { IMainState } from '../../interactive-common/mainState'; +import { CommonActionType, CommonActionTypeMapping } from '../../interactive-common/redux/reducers/types'; import { ReducerArg, ReducerFunc } from '../../react-common/reduxUtils'; -type NativeEditorReducerFunc = T extends never | undefined - ? ReducerFunc - : T extends PrimitiveTypeInReduxActionPayload - ? ReducerFunc - : ReducerFunc; +type NativeEditorReducerFunc = ReducerFunc>; -export type NativeEditorReducerArg = T extends never | undefined - ? ReducerArg - : T extends PrimitiveTypeInReduxActionPayload - ? ReducerArg - : ReducerArg; +export type NativeEditorReducerArg = ReducerArg>; -export class INativeEditorActionMapping { - public [CommonActionType.INSERT_ABOVE]: NativeEditorReducerFunc; - public [CommonActionType.INSERT_BELOW]: NativeEditorReducerFunc; - public [CommonActionType.INSERT_ABOVE_FIRST]: NativeEditorReducerFunc; - public [CommonActionType.FOCUS_CELL]: NativeEditorReducerFunc; - public [CommonActionType.UNFOCUS_CELL]: NativeEditorReducerFunc; - public [CommonActionType.ADD_NEW_CELL]: NativeEditorReducerFunc; - public [CommonActionType.EXECUTE_CELL]: NativeEditorReducerFunc; - public [CommonActionType.EXECUTE_ALL_CELLS]: NativeEditorReducerFunc; - public [CommonActionType.EXECUTE_ABOVE]: NativeEditorReducerFunc; - public [CommonActionType.EXECUTE_CELL_AND_BELOW]: NativeEditorReducerFunc; - public [CommonActionType.RESTART_KERNEL]: NativeEditorReducerFunc; - public [CommonActionType.INTERRUPT_KERNEL]: NativeEditorReducerFunc; - public [CommonActionType.CLEAR_ALL_OUTPUTS]: NativeEditorReducerFunc; - public [CommonActionType.EXPORT]: NativeEditorReducerFunc; - public [CommonActionType.SAVE]: NativeEditorReducerFunc; - public [CommonActionType.UNDO]: NativeEditorReducerFunc; - public [CommonActionType.REDO]: NativeEditorReducerFunc; - public [CommonActionType.SHOW_DATA_VIEWER]: NativeEditorReducerFunc; - public [CommonActionType.SEND_COMMAND]: NativeEditorReducerFunc; - public [CommonActionType.SELECT_CELL]: NativeEditorReducerFunc; - public [CommonActionType.MOVE_CELL_UP]: NativeEditorReducerFunc; - public [CommonActionType.MOVE_CELL_DOWN]: NativeEditorReducerFunc; - public [CommonActionType.TOGGLE_LINE_NUMBERS]: NativeEditorReducerFunc; - public [CommonActionType.TOGGLE_OUTPUT]: NativeEditorReducerFunc; - public [CommonActionType.DELETE_CELL]: NativeEditorReducerFunc; - public [CommonActionType.ARROW_UP]: NativeEditorReducerFunc; - public [CommonActionType.ARROW_DOWN]: NativeEditorReducerFunc; - public [CommonActionType.CHANGE_CELL_TYPE]: NativeEditorReducerFunc; - public [CommonActionType.EDIT_CELL]: NativeEditorReducerFunc; - public [CommonActionType.LINK_CLICK]: NativeEditorReducerFunc; - public [CommonActionType.SHOW_PLOT]: NativeEditorReducerFunc; - public [CommonActionType.GATHER_CELL]: NativeEditorReducerFunc; - public [CommonActionType.EDITOR_LOADED]: NativeEditorReducerFunc; - public [CommonActionType.LOADED_ALL_CELLS]: NativeEditorReducerFunc; - public [CommonActionType.UNMOUNT]: NativeEditorReducerFunc; - public [CommonActionType.SELECT_KERNEL]: NativeEditorReducerFunc; - public [CommonActionType.SELECT_SERVER]: NativeEditorReducerFunc; +type NativeEditorReducerFunctions = { + [P in keyof T]: T[P] extends never | undefined ? NativeEditorReducerFunc : NativeEditorReducerFunc; +}; - // Messages from the extension - public [IncomingMessageActions.STARTCELL]: NativeEditorReducerFunc; - public [IncomingMessageActions.FINISHCELL]: NativeEditorReducerFunc; - public [IncomingMessageActions.UPDATECELL]: NativeEditorReducerFunc; - public [IncomingMessageActions.NOTEBOOKDIRTY]: NativeEditorReducerFunc; - public [IncomingMessageActions.NOTEBOOKCLEAN]: NativeEditorReducerFunc; - public [IncomingMessageActions.LOADALLCELLS]: NativeEditorReducerFunc; - public [IncomingMessageActions.NOTEBOOKRUNALLCELLS]: NativeEditorReducerFunc; - public [IncomingMessageActions.NOTEBOOKRUNSELECTEDCELL]: NativeEditorReducerFunc; - public [IncomingMessageActions.NOTEBOOKADDCELLBELOW]: NativeEditorReducerFunc; - public [IncomingMessageActions.DOSAVE]: NativeEditorReducerFunc; - public [IncomingMessageActions.DELETEALLCELLS]: NativeEditorReducerFunc; - public [IncomingMessageActions.UNDO]: NativeEditorReducerFunc; - public [IncomingMessageActions.REDO]: NativeEditorReducerFunc; - public [IncomingMessageActions.STARTPROGRESS]: NativeEditorReducerFunc; - public [IncomingMessageActions.STOPPROGRESS]: NativeEditorReducerFunc; - public [IncomingMessageActions.UPDATESETTINGS]: NativeEditorReducerFunc; - public [IncomingMessageActions.ACTIVATE]: NativeEditorReducerFunc; - public [IncomingMessageActions.RESTARTKERNEL]: NativeEditorReducerFunc; - public [IncomingMessageActions.GETCSSRESPONSE]: NativeEditorReducerFunc; - public [IncomingMessageActions.MONACOREADY]: NativeEditorReducerFunc; - public [IncomingMessageActions.GETMONACOTHEMERESPONSE]: NativeEditorReducerFunc; - public [IncomingMessageActions.UPDATEKERNEL]: NativeEditorReducerFunc; - public [IncomingMessageActions.LOCINIT]: NativeEditorReducerFunc; -} +export type INativeEditorActionMapping = NativeEditorReducerFunctions & NativeEditorReducerFunctions; diff --git a/src/datascience-ui/native-editor/redux/reducers/creation.ts b/src/datascience-ui/native-editor/redux/reducers/creation.ts index fad4c7d3c92f..fcc37eff9e6b 100644 --- a/src/datascience-ui/native-editor/redux/reducers/creation.ts +++ b/src/datascience-ui/native-editor/redux/reducers/creation.ts @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. 'use strict'; -import * as uuid from 'uuid/v4'; import { ILoadAllCells, InteractiveWindowMessages } from '../../../../client/datascience/interactive-common/interactiveWindowTypes'; import { ICell, IDataScienceExtraSettings } from '../../../../client/datascience/types'; @@ -38,11 +37,11 @@ export namespace Creation { } export function insertAbove(arg: NativeEditorReducerArg): IMainState { - const newVM = prepareCellVM(createEmptyCell(arg.payload.newCellId || uuid(), null), false, arg.prevState.settings); + const newVM = prepareCellVM(createEmptyCell(arg.payload.data.newCellId, null), false, arg.prevState.settings); const newList = [...arg.prevState.cellVMs]; // Find the position where we want to insert - let position = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); + let position = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); if (position >= 0) { newList.splice(position, 0, newVM); } else { @@ -70,11 +69,11 @@ export namespace Creation { } export function insertBelow(arg: NativeEditorReducerArg): IMainState { - const newVM = prepareCellVM(createEmptyCell(arg.payload.newCellId || uuid(), null), false, arg.prevState.settings); + const newVM = prepareCellVM(createEmptyCell(arg.payload.data.newCellId, null), false, arg.prevState.settings); const newList = [...arg.prevState.cellVMs]; // Find the position where we want to insert - let position = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); + let position = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); let index = 0; if (position >= 0) { newList.splice(position + 1, 0, newVM); @@ -109,12 +108,12 @@ export namespace Creation { const firstCellId = arg.prevState.cellVMs.length > 0 ? arg.prevState.cellVMs[0].cell.id : undefined; // Do what an insertAbove does - return insertAbove({ ...arg, payload: { cellId: firstCellId, newCellId: arg.payload.newCellId } }); + return insertAbove({ ...arg, payload: { ...arg.payload, data: { cellId: firstCellId, newCellId: arg.payload.data.newCellId } } }); } export function addNewCell(arg: NativeEditorReducerArg): IMainState { // Do the same thing that an insertBelow does using the currently selected cell. - return insertBelow({ ...arg, payload: { cellId: arg.prevState.selectedCellId, newCellId: arg.payload.newCellId } }); + return insertBelow({ ...arg, payload: { ...arg.payload, data: { cellId: arg.prevState.selectedCellId, newCellId: arg.payload.data.newCellId } } }); } export function startCell(arg: NativeEditorReducerArg): IMainState { @@ -135,7 +134,7 @@ export namespace Creation { // Just leave one single blank empty cell const newVM: ICellViewModel = { - cell: createEmptyCell(arg.payload.newCellId, null), + cell: createEmptyCell(arg.payload.data.newCellId, null), editable: true, inputBlockOpen: true, inputBlockShow: true, @@ -161,10 +160,10 @@ export namespace Creation { export function deleteCell(arg: NativeEditorReducerArg): IMainState { const cells = arg.prevState.cellVMs; - if (cells.length === 1 && cells[0].cell.id === arg.payload.cellId) { + if (cells.length === 1 && cells[0].cell.id === arg.payload.data.cellId) { // Special case, if this is the last cell, don't delete it, just clear it's output and input const newVM: ICellViewModel = { - cell: createEmptyCell(arg.payload.cellId, null), + cell: createEmptyCell(arg.payload.data.cellId, null), editable: true, inputBlockOpen: true, inputBlockShow: true, @@ -179,7 +178,7 @@ export namespace Creation { // Send messages to other side to indicate the new add arg.queueAction(createPostableAction(InteractiveWindowMessages.DeleteCell)); - arg.queueAction(createPostableAction(InteractiveWindowMessages.RemoveCell, { id: arg.payload.cellId })); + arg.queueAction(createPostableAction(InteractiveWindowMessages.RemoveCell, { id: arg.payload.data.cellId })); arg.queueAction(createPostableAction(InteractiveWindowMessages.InsertCell, { cell: newVM.cell, code: '', index: 0, codeCellAboveId: undefined })); return { @@ -187,21 +186,21 @@ export namespace Creation { undoStack: Helpers.pushStack(arg.prevState.undoStack, arg.prevState.cellVMs), cellVMs: [newVM] }; - } else if (arg.payload.cellId) { + } else if (arg.payload.data.cellId) { // Otherwise just a straight delete - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); if (index >= 0) { arg.queueAction(createPostableAction(InteractiveWindowMessages.DeleteCell)); - arg.queueAction(createPostableAction(InteractiveWindowMessages.RemoveCell, { id: arg.payload.cellId })); + arg.queueAction(createPostableAction(InteractiveWindowMessages.RemoveCell, { id: arg.payload.data.cellId })); // Recompute select/focus if this item has either let newSelection = arg.prevState.selectedCellId; let newFocused = arg.prevState.focusedCellId; - const newVMs = [...arg.prevState.cellVMs.filter(c => c.cell.id !== arg.payload.cellId)]; + const newVMs = [...arg.prevState.cellVMs.filter(c => c.cell.id !== arg.payload.data.cellId)]; const nextOrPrev = index === arg.prevState.cellVMs.length - 1 ? index - 1 : index; - if (arg.prevState.selectedCellId === arg.payload.cellId || arg.prevState.focusedCellId === arg.payload.cellId) { + if (arg.prevState.selectedCellId === arg.payload.data.cellId || arg.prevState.focusedCellId === arg.payload.data.cellId) { if (nextOrPrev >= 0) { - newVMs[nextOrPrev] = { ...newVMs[nextOrPrev], selected: true, focused: arg.prevState.focusedCellId === arg.payload.cellId }; + newVMs[nextOrPrev] = { ...newVMs[nextOrPrev], selected: true, focused: arg.prevState.focusedCellId === arg.payload.data.cellId }; newSelection = newVMs[nextOrPrev].cell.id; newFocused = newVMs[nextOrPrev].focused ? newVMs[nextOrPrev].cell.id : undefined; } @@ -222,11 +221,11 @@ export namespace Creation { } export function loadAllCells(arg: NativeEditorReducerArg): IMainState { - const vms = arg.payload.cells.map(c => prepareCellVM(c, false, arg.prevState.settings)); + const vms = arg.payload.data.cells.map(c => prepareCellVM(c, false, arg.prevState.settings)); return { ...arg.prevState, busy: false, - loadTotal: arg.payload.cells.length, + loadTotal: arg.payload.data.cells.length, undoStack: [], cellVMs: vms, loaded: true diff --git a/src/datascience-ui/native-editor/redux/reducers/effects.ts b/src/datascience-ui/native-editor/redux/reducers/effects.ts index 8a72aec1eb08..8b3a3b45ad6a 100644 --- a/src/datascience-ui/native-editor/redux/reducers/effects.ts +++ b/src/datascience-ui/native-editor/redux/reducers/effects.ts @@ -13,7 +13,7 @@ import { NativeEditorReducerArg } from '../mapping'; export namespace Effects { export function focusCell(arg: NativeEditorReducerArg): IMainState { // Do nothing if already the focused cell. - if (arg.prevState.focusedCellId !== arg.payload.cellId) { + if (arg.prevState.focusedCellId !== arg.payload.data.cellId) { let prevState = arg.prevState; // First find the old focused cell and unfocus it @@ -25,23 +25,23 @@ export namespace Effects { if (removeFocusIndex >= 0) { const oldFocusCell = prevState.cellVMs[removeFocusIndex]; const oldCode = oldFocusCell.uncomittedText || oldFocusCell.inputBlockText; - prevState = unfocusCell({ ...arg, prevState, payload: { cellId: prevState.cellVMs[removeFocusIndex].cell.id, code: oldCode } }); - prevState = deselectCell({ ...arg, prevState, payload: { cellId: prevState.cellVMs[removeFocusIndex].cell.id } }); + prevState = unfocusCell({ ...arg, prevState, payload: { ...arg.payload, data: { cellId: prevState.cellVMs[removeFocusIndex].cell.id, code: oldCode } } }); + prevState = deselectCell({ ...arg, prevState, payload: { ...arg.payload, data: { cellId: prevState.cellVMs[removeFocusIndex].cell.id } } }); } const newVMs = [...prevState.cellVMs]; // Add focus on new cell - const addFocusIndex = newVMs.findIndex(c => c.cell.id === arg.payload.cellId); + const addFocusIndex = newVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); if (addFocusIndex >= 0) { - newVMs[addFocusIndex] = { ...newVMs[addFocusIndex], focused: true, selected: true, cursorPos: arg.payload.cursorPos }; + newVMs[addFocusIndex] = { ...newVMs[addFocusIndex], focused: true, selected: true, cursorPos: arg.payload.data.cursorPos }; } return { ...prevState, cellVMs: newVMs, - focusedCellId: arg.payload.cellId, - selectedCellId: arg.payload.cellId + focusedCellId: arg.payload.data.cellId, + selectedCellId: arg.payload.data.cellId }; } @@ -50,19 +50,19 @@ export namespace Effects { export function unfocusCell(arg: NativeEditorReducerArg): IMainState { // Unfocus the cell - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); - if (index >= 0 && arg.prevState.focusedCellId === arg.payload.cellId) { + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); + if (index >= 0 && arg.prevState.focusedCellId === arg.payload.data.cellId) { const newVMs = [...arg.prevState.cellVMs]; const current = arg.prevState.cellVMs[index]; const newCell = { ...current, - inputBlockText: arg.payload.code, + inputBlockText: arg.payload.data.code, focused: false, cell: { ...current.cell, data: { ...current.cell.data, - source: arg.payload.code + source: arg.payload.data.code } } }; @@ -81,12 +81,12 @@ export namespace Effects { const current = arg.prevState.cellVMs[index]; const newCell = { ...current, - inputBlockText: arg.payload.code, + inputBlockText: arg.payload.data.code, cell: { ...current.cell, data: { ...current.cell.data, - source: arg.payload.code + source: arg.payload.data.code } } }; @@ -104,8 +104,8 @@ export namespace Effects { } export function deselectCell(arg: NativeEditorReducerArg): IMainState { - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); - if (index >= 0 && arg.prevState.selectedCellId === arg.payload.cellId) { + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); + if (index >= 0 && arg.prevState.selectedCellId === arg.payload.data.cellId) { const newVMs = [...arg.prevState.cellVMs]; const target = arg.prevState.cellVMs[index]; const newCell = { @@ -128,9 +128,9 @@ export namespace Effects { export function selectCell(arg: NativeEditorReducerArg): IMainState { // Skip doing anything if already selected. - if (arg.payload.cellId !== arg.prevState.selectedCellId) { + if (arg.payload.data.cellId !== arg.prevState.selectedCellId) { let prevState = arg.prevState; - const addIndex = prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); + const addIndex = prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); // First find the old focused cell and unfocus it let removeFocusIndex = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.prevState.focusedCellId); @@ -141,32 +141,32 @@ export namespace Effects { if (removeFocusIndex >= 0) { const oldFocusCell = prevState.cellVMs[removeFocusIndex]; const oldCode = oldFocusCell.uncomittedText || oldFocusCell.inputBlockText; - prevState = unfocusCell({ ...arg, prevState, payload: { cellId: prevState.cellVMs[removeFocusIndex].cell.id, code: oldCode } }); - prevState = deselectCell({ ...arg, prevState, payload: { cellId: prevState.cellVMs[removeFocusIndex].cell.id } }); + prevState = unfocusCell({ ...arg, prevState, payload: { ...arg.payload, data: { cellId: prevState.cellVMs[removeFocusIndex].cell.id, code: oldCode } } }); + prevState = deselectCell({ ...arg, prevState, payload: { ...arg.payload, data: { cellId: prevState.cellVMs[removeFocusIndex].cell.id } } }); } const newVMs = [...prevState.cellVMs]; - if (addIndex >= 0 && arg.payload.cellId !== prevState.selectedCellId) { + if (addIndex >= 0 && arg.payload.data.cellId !== prevState.selectedCellId) { newVMs[addIndex] = { ...newVMs[addIndex], focused: prevState.focusedCellId !== undefined && prevState.focusedCellId === prevState.selectedCellId, selected: true, - cursorPos: arg.payload.cursorPos + cursorPos: arg.payload.data.cursorPos }; } return { ...prevState, cellVMs: newVMs, - focusedCellId: prevState.focusedCellId !== undefined ? arg.payload.cellId : undefined, - selectedCellId: arg.payload.cellId + focusedCellId: prevState.focusedCellId !== undefined ? arg.payload.data.cellId : undefined, + selectedCellId: arg.payload.data.cellId }; } return arg.prevState; } export function toggleLineNumbers(arg: NativeEditorReducerArg): IMainState { - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); if (index >= 0) { const newVMs = [...arg.prevState.cellVMs]; newVMs[index] = { ...newVMs[index], showLineNumbers: !newVMs[index].showLineNumbers }; @@ -179,7 +179,7 @@ export namespace Effects { } export function toggleOutput(arg: NativeEditorReducerArg): IMainState { - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); if (index >= 0) { const newVMs = [...arg.prevState.cellVMs]; newVMs[index] = { ...newVMs[index], hideOutput: !newVMs[index].hideOutput }; diff --git a/src/datascience-ui/native-editor/redux/reducers/execution.ts b/src/datascience-ui/native-editor/redux/reducers/execution.ts index ed51ae4fffe9..cbd630c6c522 100644 --- a/src/datascience-ui/native-editor/redux/reducers/execution.ts +++ b/src/datascience-ui/native-editor/redux/reducers/execution.ts @@ -54,7 +54,7 @@ export namespace Execution { } export function executeAbove(arg: NativeEditorReducerArg): IMainState { - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); if (index > 0) { const codes = arg.prevState.cellVMs.filter((_c, i) => i < index).map(c => concatMultilineStringInput(c.cell.data.source)); return executeRange(arg.prevState, 0, index - 1, codes, arg.queueAction); @@ -63,17 +63,17 @@ export namespace Execution { } export function executeCell(arg: NativeEditorReducerArg): IMainState { - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); if (index >= 0) { // Start executing this cell. - const executeResult = executeRange(arg.prevState, index, index, [arg.payload.code], arg.queueAction); + const executeResult = executeRange(arg.prevState, index, index, [arg.payload.data.code], arg.queueAction); // Modify the execute result if moving // Use `if` instead of `switch case` to ensure type safety. - if (arg.payload.moveOp === 'add') { + if (arg.payload.data.moveOp === 'add') { // Add a new cell below - return Creation.insertBelow({ ...arg, prevState: executeResult, payload: { ...arg.payload } }); - } else if (arg.payload.moveOp === 'select') { + return Creation.insertBelow({ ...arg, prevState: executeResult, payload: { ...arg.payload, data: { ...arg.payload.data } } }); + } else if (arg.payload.data.moveOp === 'select') { // Select the cell below this one, but don't focus it if (index < arg.prevState.cellVMs.length - 1) { return Effects.selectCell({ @@ -83,8 +83,11 @@ export namespace Execution { }, payload: { ...arg.payload, - cellId: arg.prevState.cellVMs[index + 1].cell.id, - cursorPos: CursorPos.Current + data: { + ...arg.payload.data, + cellId: arg.prevState.cellVMs[index + 1].cell.id, + cursorPos: CursorPos.Current + } } }); } @@ -97,10 +100,10 @@ export namespace Execution { } export function executeCellAndBelow(arg: NativeEditorReducerArg): IMainState { - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); if (index >= 0) { const codes = arg.prevState.cellVMs.filter((_c, i) => i > index).map(c => concatMultilineStringInput(c.cell.data.source)); - return executeRange(arg.prevState, index, index + codes.length, [arg.payload.code, ...codes], arg.queueAction); + return executeRange(arg.prevState, index, index + codes.length, [arg.payload.data.code, ...codes], arg.queueAction); } return arg.prevState; } @@ -109,7 +112,10 @@ export namespace Execution { // This is the same thing as executing the first cell and all below const firstCell = arg.prevState.cellVMs.length > 0 ? arg.prevState.cellVMs[0].cell.id : undefined; if (firstCell) { - return executeCellAndBelow({ ...arg, payload: { cellId: firstCell, code: concatMultilineStringInput(arg.prevState.cellVMs[0].cell.data.source) } }); + return executeCellAndBelow({ + ...arg, + payload: { ...arg.payload, data: { cellId: firstCell, code: concatMultilineStringInput(arg.prevState.cellVMs[0].cell.data.source) } } + }); } return arg.prevState; @@ -121,7 +127,10 @@ export namespace Execution { if (arg.prevState.selectedCellId && index >= 0) { return executeCell({ ...arg, - payload: { cellId: arg.prevState.selectedCellId, code: concatMultilineStringInput(arg.prevState.cellVMs[index].cell.data.source), moveOp: 'none' } + payload: { + ...arg.payload, + data: { cellId: arg.prevState.selectedCellId, code: concatMultilineStringInput(arg.prevState.cellVMs[index].cell.data.source), moveOp: 'none' } + } }); } @@ -142,16 +151,16 @@ export namespace Execution { } export function changeCellType(arg: NativeEditorReducerArg): IMainState { - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); if (index >= 0) { const cellVMs = [...arg.prevState.cellVMs]; const current = arg.prevState.cellVMs[index]; const newType = current.cell.data.cell_type === 'code' ? 'markdown' : 'code'; const newNotebookCell = createCellFrom(current.cell.data, newType); - newNotebookCell.source = arg.payload.currentCode; + newNotebookCell.source = arg.payload.data.currentCode; const newCell: ICellViewModel = { ...current, - inputBlockText: arg.payload.currentCode, + inputBlockText: arg.payload.data.currentCode, cell: { ...current.cell, data: newNotebookCell @@ -164,7 +173,7 @@ export namespace Execution { createPostableAction(InteractiveWindowMessages.InsertCell, { cell: cellVMs[index].cell, index, - code: arg.payload.currentCode, + code: arg.payload.data.currentCode, codeCellAboveId: Helpers.firstCodeCellAbove(arg.prevState, current.cell.id) }) ); @@ -173,7 +182,11 @@ export namespace Execution { } // When changing a cell type, also give the cell focus. - return Effects.focusCell({ ...arg, prevState: { ...arg.prevState, cellVMs }, payload: { cellId: arg.payload.cellId, cursorPos: CursorPos.Current } }); + return Effects.focusCell({ + ...arg, + prevState: { ...arg.prevState, cellVMs }, + payload: { ...arg.payload, data: { cellId: arg.payload.data.cellId, cursorPos: CursorPos.Current } } + }); } return arg.prevState; diff --git a/src/datascience-ui/native-editor/redux/reducers/index.ts b/src/datascience-ui/native-editor/redux/reducers/index.ts index 88daa9375dc0..ce91ddd0101e 100644 --- a/src/datascience-ui/native-editor/redux/reducers/index.ts +++ b/src/datascience-ui/native-editor/redux/reducers/index.ts @@ -1,7 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. 'use strict'; -import { IncomingMessageActions } from '../../../interactive-common/redux/postOffice'; +import { InteractiveWindowMessages } from '../../../../client/datascience/interactive-common/interactiveWindowTypes'; +import { CssMessages, SharedMessages } from '../../../../client/datascience/messages'; import { CommonEffects } from '../../../interactive-common/redux/reducers/commonEffects'; import { Kernel } from '../../../interactive-common/redux/reducers/kernel'; import { Transfer } from '../../../interactive-common/redux/reducers/transfer'; @@ -13,7 +14,7 @@ import { Execution } from './execution'; import { Movement } from './movement'; // The list of reducers. 1 per message/action. -export const reducerMap: INativeEditorActionMapping = { +export const reducerMap: Partial = { // State updates [CommonActionType.INSERT_ABOVE]: Creation.insertAbove, [CommonActionType.INSERT_ABOVE_FIRST]: Creation.insertAboveFirst, @@ -27,26 +28,26 @@ export const reducerMap: INativeEditorActionMapping = { [CommonActionType.EXECUTE_CELL_AND_BELOW]: Execution.executeCellAndBelow, [CommonActionType.RESTART_KERNEL]: Kernel.restartKernel, [CommonActionType.INTERRUPT_KERNEL]: Kernel.interruptKernel, - [CommonActionType.CLEAR_ALL_OUTPUTS]: Execution.clearAllOutputs, + [InteractiveWindowMessages.ClearAllOutputs]: Execution.clearAllOutputs, [CommonActionType.EXPORT]: Transfer.exportCells, [CommonActionType.SAVE]: Transfer.save, [CommonActionType.SHOW_DATA_VIEWER]: Transfer.showDataViewer, [CommonActionType.SEND_COMMAND]: Transfer.sendCommand, [CommonActionType.SELECT_CELL]: Effects.selectCell, - [CommonActionType.SELECT_KERNEL]: Kernel.selectKernel, + [InteractiveWindowMessages.SelectKernel]: Kernel.selectKernel, [CommonActionType.SELECT_SERVER]: Kernel.selectJupyterURI, [CommonActionType.MOVE_CELL_UP]: Movement.moveCellUp, [CommonActionType.MOVE_CELL_DOWN]: Movement.moveCellDown, - [CommonActionType.DELETE_CELL]: Creation.deleteCell, + [InteractiveWindowMessages.DeleteCell]: Creation.deleteCell, [CommonActionType.TOGGLE_LINE_NUMBERS]: Effects.toggleLineNumbers, [CommonActionType.TOGGLE_OUTPUT]: Effects.toggleOutput, [CommonActionType.CHANGE_CELL_TYPE]: Execution.changeCellType, - [CommonActionType.UNDO]: Execution.undo, - [CommonActionType.REDO]: Execution.redo, + [InteractiveWindowMessages.Undo]: Execution.undo, + [InteractiveWindowMessages.Redo]: Execution.redo, [CommonActionType.ARROW_UP]: Movement.arrowUp, [CommonActionType.ARROW_DOWN]: Movement.arrowDown, [CommonActionType.EDIT_CELL]: Transfer.editCell, - [CommonActionType.SHOW_PLOT]: Transfer.showPlot, + [InteractiveWindowMessages.ShowPlot]: Transfer.showPlot, [CommonActionType.LINK_CLICK]: Transfer.linkClick, [CommonActionType.GATHER_CELL]: Transfer.gather, [CommonActionType.EDITOR_LOADED]: Transfer.started, @@ -54,27 +55,27 @@ export const reducerMap: INativeEditorActionMapping = { [CommonActionType.UNMOUNT]: Creation.unmount, // Messages from the webview (some are ignored) - [IncomingMessageActions.STARTCELL]: Creation.startCell, - [IncomingMessageActions.FINISHCELL]: Creation.finishCell, - [IncomingMessageActions.UPDATECELL]: Creation.updateCell, - [IncomingMessageActions.NOTEBOOKDIRTY]: CommonEffects.notebookDirty, - [IncomingMessageActions.NOTEBOOKCLEAN]: CommonEffects.notebookClean, - [IncomingMessageActions.LOADALLCELLS]: Creation.loadAllCells, - [IncomingMessageActions.NOTEBOOKRUNALLCELLS]: Execution.executeAllCells, - [IncomingMessageActions.NOTEBOOKRUNSELECTEDCELL]: Execution.executeSelectedCell, - [IncomingMessageActions.NOTEBOOKADDCELLBELOW]: Creation.addNewCell, - [IncomingMessageActions.DOSAVE]: Transfer.save, - [IncomingMessageActions.DELETEALLCELLS]: Creation.deleteAllCells, - [IncomingMessageActions.UNDO]: Execution.undo, - [IncomingMessageActions.REDO]: Execution.redo, - [IncomingMessageActions.STARTPROGRESS]: CommonEffects.startProgress, - [IncomingMessageActions.STOPPROGRESS]: CommonEffects.stopProgress, - [IncomingMessageActions.UPDATESETTINGS]: Effects.updateSettings, - [IncomingMessageActions.ACTIVATE]: CommonEffects.activate, - [IncomingMessageActions.RESTARTKERNEL]: Kernel.handleRestarted, - [IncomingMessageActions.GETCSSRESPONSE]: CommonEffects.handleCss, - [IncomingMessageActions.MONACOREADY]: CommonEffects.monacoReady, - [IncomingMessageActions.GETMONACOTHEMERESPONSE]: CommonEffects.monacoThemeChange, - [IncomingMessageActions.UPDATEKERNEL]: Kernel.updateStatus, - [IncomingMessageActions.LOCINIT]: CommonEffects.handleLocInit + [InteractiveWindowMessages.StartCell]: Creation.startCell, + [InteractiveWindowMessages.FinishCell]: Creation.finishCell, + [InteractiveWindowMessages.UpdateCell]: Creation.updateCell, + [InteractiveWindowMessages.NotebookDirty]: CommonEffects.notebookDirty, + [InteractiveWindowMessages.NotebookClean]: CommonEffects.notebookClean, + [InteractiveWindowMessages.LoadAllCells]: Creation.loadAllCells, + [InteractiveWindowMessages.NotebookRunAllCells]: Execution.executeAllCells, + [InteractiveWindowMessages.NotebookRunSelectedCell]: Execution.executeSelectedCell, + [InteractiveWindowMessages.NotebookAddCellBelow]: Creation.addNewCell, + [InteractiveWindowMessages.DoSave]: Transfer.save, + [InteractiveWindowMessages.DeleteAllCells]: Creation.deleteAllCells, + [InteractiveWindowMessages.Undo]: Execution.undo, + [InteractiveWindowMessages.Redo]: Execution.redo, + [InteractiveWindowMessages.StartProgress]: CommonEffects.startProgress, + [InteractiveWindowMessages.StopProgress]: CommonEffects.stopProgress, + [SharedMessages.UpdateSettings]: Effects.updateSettings, + [InteractiveWindowMessages.Activate]: CommonEffects.activate, + [InteractiveWindowMessages.RestartKernel]: Kernel.handleRestarted, + [CssMessages.GetCssResponse]: CommonEffects.handleCss, + [InteractiveWindowMessages.MonacoReady]: CommonEffects.monacoReady, + [CssMessages.GetMonacoThemeResponse]: CommonEffects.monacoThemeChange, + [InteractiveWindowMessages.UpdateKernel]: Kernel.updateStatus, + [SharedMessages.LocInit]: CommonEffects.handleLocInit }; diff --git a/src/datascience-ui/native-editor/redux/reducers/movement.ts b/src/datascience-ui/native-editor/redux/reducers/movement.ts index ca8d51aa6120..8f0b19ec8ee9 100644 --- a/src/datascience-ui/native-editor/redux/reducers/movement.ts +++ b/src/datascience-ui/native-editor/redux/reducers/movement.ts @@ -12,10 +12,10 @@ import { Effects } from './effects'; export namespace Movement { export function moveCellUp(arg: NativeEditorReducerArg): IMainState { const newVMs = [...arg.prevState.cellVMs]; - const index = newVMs.findIndex(cvm => cvm.cell.id === arg.payload.cellId); + const index = newVMs.findIndex(cvm => cvm.cell.id === arg.payload.data.cellId); if (index > 0) { [newVMs[index - 1], newVMs[index]] = [newVMs[index], newVMs[index - 1]]; - arg.queueAction(createPostableAction(InteractiveWindowMessages.SwapCells, { firstCellId: arg.payload.cellId!, secondCellId: newVMs[index].cell.id })); + arg.queueAction(createPostableAction(InteractiveWindowMessages.SwapCells, { firstCellId: arg.payload.data.cellId!, secondCellId: newVMs[index].cell.id })); return { ...arg.prevState, cellVMs: newVMs, @@ -28,10 +28,10 @@ export namespace Movement { export function moveCellDown(arg: NativeEditorReducerArg): IMainState { const newVMs = [...arg.prevState.cellVMs]; - const index = newVMs.findIndex(cvm => cvm.cell.id === arg.payload.cellId); + const index = newVMs.findIndex(cvm => cvm.cell.id === arg.payload.data.cellId); if (index < newVMs.length - 1) { [newVMs[index + 1], newVMs[index]] = [newVMs[index], newVMs[index + 1]]; - arg.queueAction(createPostableAction(InteractiveWindowMessages.SwapCells, { firstCellId: arg.payload.cellId!, secondCellId: newVMs[index].cell.id })); + arg.queueAction(createPostableAction(InteractiveWindowMessages.SwapCells, { firstCellId: arg.payload.data.cellId!, secondCellId: newVMs[index].cell.id })); return { ...arg.prevState, cellVMs: newVMs, @@ -43,14 +43,14 @@ export namespace Movement { } export function arrowUp(arg: NativeEditorReducerArg): IMainState { - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); if (index > 0) { - const newState = Effects.selectCell({ ...arg, payload: { cellId: arg.prevState.cellVMs[index - 1].cell.id, cursorPos: CursorPos.Bottom } }); + const newState = Effects.selectCell({ ...arg, payload: { ...arg.payload, data: { cellId: arg.prevState.cellVMs[index - 1].cell.id, cursorPos: CursorPos.Bottom } } }); const newVMs = [...newState.cellVMs]; newVMs[index] = Helpers.asCellViewModel({ ...newVMs[index], - inputBlockText: arg.payload.code, - cell: { ...newVMs[index].cell, data: { ...newVMs[index].cell.data, source: arg.payload.code } } + inputBlockText: arg.payload.data.code, + cell: { ...newVMs[index].cell, data: { ...newVMs[index].cell.data, source: arg.payload.data.code } } }); return { ...newState, @@ -62,14 +62,14 @@ export namespace Movement { } export function arrowDown(arg: NativeEditorReducerArg): IMainState { - const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.cellId); + const index = arg.prevState.cellVMs.findIndex(c => c.cell.id === arg.payload.data.cellId); if (index < arg.prevState.cellVMs.length - 1) { - const newState = Effects.selectCell({ ...arg, payload: { cellId: arg.prevState.cellVMs[index + 1].cell.id, cursorPos: CursorPos.Top } }); + const newState = Effects.selectCell({ ...arg, payload: { ...arg.payload, data: { cellId: arg.prevState.cellVMs[index + 1].cell.id, cursorPos: CursorPos.Top } } }); const newVMs = [...newState.cellVMs]; newVMs[index] = Helpers.asCellViewModel({ ...newVMs[index], - inputBlockText: arg.payload.code, - cell: { ...newVMs[index].cell, data: { ...newVMs[index].cell.data, source: arg.payload.code } } + inputBlockText: arg.payload.data.code, + cell: { ...newVMs[index].cell, data: { ...newVMs[index].cell.data, source: arg.payload.data.code } } }); return { ...newState, diff --git a/src/datascience-ui/plot/mainPanel.tsx b/src/datascience-ui/plot/mainPanel.tsx index d33d4123c59e..9d1f2442a150 100644 --- a/src/datascience-ui/plot/mainPanel.tsx +++ b/src/datascience-ui/plot/mainPanel.tsx @@ -80,7 +80,7 @@ export class MainPanel extends React.Component this.postOffice.addHandler(this); // Tell the plot viewer code we have started. - this.postOffice.sendMessage(PlotViewerMessages.Started); + this.postOffice.sendMessage(PlotViewerMessages.Started); // Listen to key events window.addEventListener('keydown', this.onKeyDown); diff --git a/src/datascience-ui/react-common/postOffice.ts b/src/datascience-ui/react-common/postOffice.ts index 524721a7b6c0..899611d53830 100644 --- a/src/datascience-ui/react-common/postOffice.ts +++ b/src/datascience-ui/react-common/postOffice.ts @@ -3,7 +3,6 @@ 'use strict'; import { WebPanelMessage } from '../../client/common/application/types'; import { IDisposable } from '../../client/common/types'; -import { noop } from '../../client/common/utils/misc'; import { logMessage } from './logger'; export interface IVsCodeApi { @@ -69,60 +68,12 @@ export class PostOffice implements IDisposable { if (!this.vscodeApi && typeof acquireVsCodeApi !== 'undefined') { this.vscodeApi = acquireVsCodeApi(); // NOSONAR } - let rewireConsole = false; if (!this.registered) { - rewireConsole = true; + // rewireConsole = true; this.registered = true; window.addEventListener('message', this.baseHandler); } - if (this.vscodeApi && rewireConsole) { - const originalConsole = window.console; - const vscodeApi = this.vscodeApi; - // Replace console.log with sending a message - const customConsole = { - ...originalConsole, - // tslint:disable-next-line: no-any no-function-expression - log: function(message?: any, ..._optionalParams: any[]) { - try { - originalConsole.log.apply(arguments); - vscodeApi?.postMessage({ type: 'console_log', payload: message }); - } catch { - noop(); - } - }, - // tslint:disable-next-line: no-any no-function-expression - info: function(message?: any, ..._optionalParams: any[]) { - try { - originalConsole.info.apply(arguments); - vscodeApi?.postMessage({ type: 'console_info', payload: message }); - } catch { - noop(); - } - }, - // tslint:disable-next-line: no-any no-function-expression - error: function(message?: any, ..._optionalParams: any[]) { - try { - originalConsole.error.apply(arguments); - vscodeApi?.postMessage({ type: 'console_error', payload: message }); - } catch { - noop(); - } - }, - // tslint:disable-next-line: no-any no-function-expression - warn: function(message?: any, ..._optionalParams: any[]) { - try { - originalConsole.warn.apply(arguments); - vscodeApi?.postMessage({ type: 'console_warn', payload: message }); - } catch { - noop(); - } - } - }; - // tslint:disable-next-line: no-any - (window as any).console = customConsole; - } - return this.vscodeApi; } diff --git a/src/datascience-ui/react-common/reduxUtils.ts b/src/datascience-ui/react-common/reduxUtils.ts index 359fc2c0dfc4..451fa74115bb 100644 --- a/src/datascience-ui/react-common/reduxUtils.ts +++ b/src/datascience-ui/react-common/reduxUtils.ts @@ -3,7 +3,6 @@ 'use strict'; import { Action, AnyAction, Middleware, Reducer } from 'redux'; import { BaseReduxActionPayload } from '../../client/datascience/interactive-common/types'; -import { PrimitiveTypeInReduxActionPayload } from '../interactive-common/redux/reducers/types'; // tslint:disable-next-line: interface-name interface TypedAnyAction extends Action { @@ -13,7 +12,7 @@ interface TypedAnyAction extends Action { } export type QueueAnotherFunc = (nextAction: Action) => void; export type QueuableAction = TypedAnyAction & { queueAction: QueueAnotherFunc }; -export type ReducerArg = T extends never | undefined +export type ReducerArg = T extends never | undefined ? { prevState: S; queueAction: QueueAnotherFunc; @@ -26,11 +25,8 @@ export type ReducerArg = T extends never | undefined }; export type ReducerFunc = (args: ReducerArg) => S; -export type ActionWithPayload = T extends never | undefined - ? TypedAnyAction & { payload?: BaseReduxActionPayload } - : T extends PrimitiveTypeInReduxActionPayload - ? TypedAnyAction & { payload: { data: T } & BaseReduxActionPayload } - : TypedAnyAction & { payload: T & BaseReduxActionPayload }; +export type ActionWithPayload = TypedAnyAction & { payload: BaseReduxActionPayload }; +export type ActionWithOutPayloadData = TypedAnyAction & { payload: BaseReduxActionPayload }; /** * CombineReducers takes in a map of action.type to func and creates a reducer that will call the appropriate function for From fc5f05116a2bbd053db586b59b97b772bdc15f66 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Fri, 31 Jan 2020 15:29:58 -0800 Subject: [PATCH 5/9] Remove console logs --- src/datascience-ui/history-react/redux/reducers/creation.ts | 1 - src/datascience-ui/history-react/redux/reducers/effects.ts | 1 - .../interactive-common/redux/reducers/commonEffects.ts | 1 - 3 files changed, 3 deletions(-) diff --git a/src/datascience-ui/history-react/redux/reducers/creation.ts b/src/datascience-ui/history-react/redux/reducers/creation.ts index 1ecd2bbedaba..b9630fb593be 100644 --- a/src/datascience-ui/history-react/redux/reducers/creation.ts +++ b/src/datascience-ui/history-react/redux/reducers/creation.ts @@ -114,7 +114,6 @@ export namespace Creation { } export function deleteAllCells(arg: InteractiveReducerArg): IMainState { - // TODO: In Native Editor, we create a new blank cell, don't we need that here? // Send messages to other side to indicate the deletes arg.queueAction(createPostableAction(InteractiveWindowMessages.DeleteAllCells)); diff --git a/src/datascience-ui/history-react/redux/reducers/effects.ts b/src/datascience-ui/history-react/redux/reducers/effects.ts index f854dcf19391..9d6148d53de3 100644 --- a/src/datascience-ui/history-react/redux/reducers/effects.ts +++ b/src/datascience-ui/history-react/redux/reducers/effects.ts @@ -51,7 +51,6 @@ export namespace Effects { } export function updateSettings(arg: InteractiveReducerArg): IMainState { - console.error(`Settings Message ${arg.payload}`); // String arg should be the IDataScienceExtraSettings const newSettingsJSON = JSON.parse(arg.payload.data); const newSettings = newSettingsJSON; diff --git a/src/datascience-ui/interactive-common/redux/reducers/commonEffects.ts b/src/datascience-ui/interactive-common/redux/reducers/commonEffects.ts index a34452dcc870..cbc7f2f7f33d 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/commonEffects.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/commonEffects.ts @@ -47,7 +47,6 @@ export namespace CommonEffects { export function handleLocInit(arg: CommonReducerArg): IMainState { // Read in the loc strings - console.error(arg.payload); const locJSON = JSON.parse(arg.payload.data); storeLocStrings(locJSON); return arg.prevState; From c922ecc760e6109dfaac8891e342a4597cbef181 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 3 Feb 2020 12:30:04 -0800 Subject: [PATCH 6/9] Disable redux logging --- src/datascience-ui/interactive-common/redux/store.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/datascience-ui/interactive-common/redux/store.ts b/src/datascience-ui/interactive-common/redux/store.ts index 5d6bd5a7a73a..9e64becf704e 100644 --- a/src/datascience-ui/interactive-common/redux/store.ts +++ b/src/datascience-ui/interactive-common/redux/store.ts @@ -212,7 +212,9 @@ function createMiddleWare(testMode: boolean): Redux.Middleware<{}, IStore>[] { results.push(testMiddleware); } if (loggerMiddleware) { - results.push(loggerMiddleware); + // results.push(loggerMiddleware); + // tslint:disable-next-line: no-console + console.log(loggerMiddleware); } return results; From b20f4738b9f7b434790dd70b6f7ea7d8f3325816 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 3 Feb 2020 14:28:17 -0800 Subject: [PATCH 7/9] Fixes --- .../interactive-common/redux/postOffice.ts | 18 +++++++++++------- .../interactive-common/redux/reducers/types.ts | 1 + 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/datascience-ui/interactive-common/redux/postOffice.ts b/src/datascience-ui/interactive-common/redux/postOffice.ts index a293d02557bd..12cee1739faf 100644 --- a/src/datascience-ui/interactive-common/redux/postOffice.ts +++ b/src/datascience-ui/interactive-common/redux/postOffice.ts @@ -7,6 +7,7 @@ import { IInteractiveWindowMapping, InteractiveWindowMessages } from '../../../c import { BaseReduxActionPayload } from '../../../client/datascience/interactive-common/types'; import { CssMessages, SharedMessages } from '../../../client/datascience/messages'; import { PostOffice } from '../../react-common/postOffice'; +import { CommonActionType } from './reducers/types'; export const AllowedMessages = [...Object.values(InteractiveWindowMessages), ...Object.values(CssMessages), ...Object.values(SharedMessages)]; @@ -17,19 +18,22 @@ export function createPostableAction; - return { type: `${message}`, payload: newPayload }; + return { type: CommonActionType.PostOutgoingMessage, payload: { payload: newPayload, type: message } }; } export function generatePostOfficeSendReducer(postOffice: PostOffice): Redux.Reducer<{}, Redux.AnyAction> { // tslint:disable-next-line: no-function-expression return function(_state: {} | undefined, action: Redux.AnyAction): {} { // Make sure a valid message - // tslint:disable-next-line: no-any - const payload: BaseReduxActionPayload<{}> | undefined = action.payload; - if (AllowedMessages.find(k => k === action.type) && payload?.messageDirection === 'outgoing') { - // Just post this to the post office. - // tslint:disable-next-line: no-any - postOffice.sendMessage(action.type, payload.data as any); + if (action.type === CommonActionType.PostOutgoingMessage) { + // Unwrap the payload that was created in `createPostableAction`. + const type = action.payload.type; + const payload: BaseReduxActionPayload<{}> | undefined = action.payload.payload; + if (AllowedMessages.find(k => k === type) && payload?.messageDirection === 'outgoing') { + // Just post this to the post office. + // tslint:disable-next-line: no-any + postOffice.sendMessage(type, payload.data as any); + } } // We don't modify the state. diff --git a/src/datascience-ui/interactive-common/redux/reducers/types.ts b/src/datascience-ui/interactive-common/redux/reducers/types.ts index 373052bc9c63..e30888cbd7a7 100644 --- a/src/datascience-ui/interactive-common/redux/reducers/types.ts +++ b/src/datascience-ui/interactive-common/redux/reducers/types.ts @@ -50,6 +50,7 @@ export enum CommonActionType { LINK_CLICK = 'action.link_click', MOVE_CELL_DOWN = 'action.move_cell_down', MOVE_CELL_UP = 'action.move_cell_up', + PostOutgoingMessage = 'action.postOutgoingMessage', REFRESH_VARIABLES = 'action.refresh_variables', RESTART_KERNEL = 'action.restart_kernel_action', SAVE = 'action.save', From 3edb7381ef1ea224b88a06aae023ac6d3c65eebb Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 3 Feb 2020 15:04:32 -0800 Subject: [PATCH 8/9] Oops --- src/datascience-ui/history-react/redux/reducers/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/datascience-ui/history-react/redux/reducers/index.ts b/src/datascience-ui/history-react/redux/reducers/index.ts index 3cbc55f3475a..d82b8b200a12 100644 --- a/src/datascience-ui/history-react/redux/reducers/index.ts +++ b/src/datascience-ui/history-react/redux/reducers/index.ts @@ -39,6 +39,8 @@ export const reducerMap: Partial = { [CommonActionType.UNMOUNT]: Creation.unmount, // Messages from the webview (some are ignored) + [InteractiveWindowMessages.Undo]: Execution.undo, + [InteractiveWindowMessages.Redo]: Execution.redo, [InteractiveWindowMessages.StartCell]: Creation.startCell, [InteractiveWindowMessages.FinishCell]: Creation.finishCell, [InteractiveWindowMessages.UpdateCell]: Creation.updateCell, From bf8982f45e91738b9c8368429c50ff88ff5b3d0c Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 3 Feb 2020 15:20:40 -0800 Subject: [PATCH 9/9] Undo unnecessary change --- src/datascience-ui/interactive-common/redux/store.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/datascience-ui/interactive-common/redux/store.ts b/src/datascience-ui/interactive-common/redux/store.ts index 9e64becf704e..5d6bd5a7a73a 100644 --- a/src/datascience-ui/interactive-common/redux/store.ts +++ b/src/datascience-ui/interactive-common/redux/store.ts @@ -212,9 +212,7 @@ function createMiddleWare(testMode: boolean): Redux.Middleware<{}, IStore>[] { results.push(testMiddleware); } if (loggerMiddleware) { - // results.push(loggerMiddleware); - // tslint:disable-next-line: no-console - console.log(loggerMiddleware); + results.push(loggerMiddleware); } return results;