fix(client): re-ref editor (#42799)
This commit is contained in:
@ -1,4 +1,11 @@
|
|||||||
import React, { useState, useEffect, Suspense, RefObject } from 'react';
|
import React, {
|
||||||
|
useState,
|
||||||
|
useEffect,
|
||||||
|
Suspense,
|
||||||
|
RefObject,
|
||||||
|
forwardRef,
|
||||||
|
ForwardedRef
|
||||||
|
} from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import Loadable from '@loadable/component';
|
import Loadable from '@loadable/component';
|
||||||
@ -34,6 +41,7 @@ import type {
|
|||||||
Range as RangeType
|
Range as RangeType
|
||||||
// eslint-disable-next-line import/no-duplicates
|
// eslint-disable-next-line import/no-duplicates
|
||||||
} from 'monaco-editor/esm/vs/editor/editor.api';
|
} from 'monaco-editor/esm/vs/editor/editor.api';
|
||||||
|
import type ReactMonacoEditor from 'react-monaco-editor';
|
||||||
|
|
||||||
import './editor.css';
|
import './editor.css';
|
||||||
|
|
||||||
@ -174,7 +182,8 @@ const initialData: DataType = {
|
|||||||
outputZoneHeight: null
|
outputZoneHeight: null
|
||||||
};
|
};
|
||||||
|
|
||||||
const Editor = (props: PropTypes): JSX.Element => {
|
const Editor = forwardRef(
|
||||||
|
(props: PropTypes, ref: ForwardedRef<ReactMonacoEditor>): JSX.Element => {
|
||||||
// TODO: is there any point in initializing this? It should be fine with
|
// TODO: is there any point in initializing this? It should be fine with
|
||||||
// data = {}
|
// data = {}
|
||||||
const [data, setData] = useState(initialData);
|
const [data, setData] = useState(initialData);
|
||||||
@ -416,7 +425,9 @@ const Editor = (props: PropTypes): JSX.Element => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const viewZoneCallback = (changeAccessor: editor.IViewZoneChangeAccessor) => {
|
const viewZoneCallback = (
|
||||||
|
changeAccessor: editor.IViewZoneChangeAccessor
|
||||||
|
) => {
|
||||||
// TODO: is there any point creating this here? I know it's cached, but
|
// TODO: is there any point creating this here? I know it's cached, but
|
||||||
// would it not be better just sourced from the overlayWidget?
|
// would it not be better just sourced from the overlayWidget?
|
||||||
const domNode = createDescription();
|
const domNode = createDescription();
|
||||||
@ -559,11 +570,6 @@ const Editor = (props: PropTypes): JSX.Element => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
function focusOnEditor() {
|
|
||||||
_editor?.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
const onChange = (editorValue: string) => {
|
const onChange = (editorValue: string) => {
|
||||||
const { updateFile } = props;
|
const { updateFile } = props;
|
||||||
// TODO: use fileKey everywhere?
|
// TODO: use fileKey everywhere?
|
||||||
@ -596,7 +602,10 @@ const Editor = (props: PropTypes): JSX.Element => {
|
|||||||
lineNumber: editableBoundaries[0] + 1,
|
lineNumber: editableBoundaries[0] + 1,
|
||||||
column: 1
|
column: 1
|
||||||
});
|
});
|
||||||
_editor?.revealLinesInCenter(editableBoundaries[0], editableBoundaries[1]);
|
_editor?.revealLinesInCenter(
|
||||||
|
editableBoundaries[0],
|
||||||
|
editableBoundaries[1]
|
||||||
|
);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,7 +766,12 @@ const Editor = (props: PropTypes): JSX.Element => {
|
|||||||
// startColumnNumber <= x < endColumnNumber
|
// startColumnNumber <= x < endColumnNumber
|
||||||
// so we add 1 here
|
// so we add 1 here
|
||||||
const endColumn = model?.getLineLength(endLineNumber) + 1;
|
const endColumn = model?.getLineLength(endLineNumber) + 1;
|
||||||
return new _monaco.Range(startLineNumber, 1, endLineNumber, endColumn);
|
return new _monaco.Range(
|
||||||
|
startLineNumber,
|
||||||
|
1,
|
||||||
|
endLineNumber,
|
||||||
|
endColumn
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -802,13 +816,15 @@ const Editor = (props: PropTypes): JSX.Element => {
|
|||||||
// the first range should expand at the top
|
// the first range should expand at the top
|
||||||
// TODO: Unsure what this should be - returns an array, so I added [0] @ojeytonwilliams
|
// TODO: Unsure what this should be - returns an array, so I added [0] @ojeytonwilliams
|
||||||
data.startEditDecId = highlightLines(
|
data.startEditDecId = highlightLines(
|
||||||
_monaco?.editor?.TrackedRangeStickiness?.GrowsOnlyWhenTypingBefore ?? 2,
|
_monaco?.editor?.TrackedRangeStickiness?.GrowsOnlyWhenTypingBefore ??
|
||||||
|
2,
|
||||||
model,
|
model,
|
||||||
ranges[0]
|
ranges[0]
|
||||||
)[0];
|
)[0];
|
||||||
|
|
||||||
highlightText(
|
highlightText(
|
||||||
_monaco?.editor?.TrackedRangeStickiness?.GrowsOnlyWhenTypingBefore ?? 2,
|
_monaco?.editor?.TrackedRangeStickiness?.GrowsOnlyWhenTypingBefore ??
|
||||||
|
2,
|
||||||
model,
|
model,
|
||||||
ranges[0]
|
ranges[0]
|
||||||
);
|
);
|
||||||
@ -834,7 +850,8 @@ const Editor = (props: PropTypes): JSX.Element => {
|
|||||||
// TODO: handle multiple simultaneous changes (multicursors do this)
|
// TODO: handle multiple simultaneous changes (multicursors do this)
|
||||||
function getDeletedLine(event: editor.IModelContentChangedEvent) {
|
function getDeletedLine(event: editor.IModelContentChangedEvent) {
|
||||||
const isDeleted =
|
const isDeleted =
|
||||||
event.changes[0].text === '' && event.changes[0].range.endColumn === 1;
|
event.changes[0].text === '' &&
|
||||||
|
event.changes[0].range.endColumn === 1;
|
||||||
return isDeleted ? event.changes[0].range.endLineNumber : 0;
|
return isDeleted ? event.changes[0].range.endLineNumber : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -971,8 +988,8 @@ const Editor = (props: PropTypes): JSX.Element => {
|
|||||||
...data,
|
...data,
|
||||||
endEditDecId: preventOverlap(
|
endEditDecId: preventOverlap(
|
||||||
data.endEditDecId ?? '',
|
data.endEditDecId ?? '',
|
||||||
_monaco?.editor?.TrackedRangeStickiness?.GrowsOnlyWhenTypingBefore ??
|
_monaco?.editor?.TrackedRangeStickiness
|
||||||
2,
|
?.GrowsOnlyWhenTypingBefore ?? 2,
|
||||||
highlightLines
|
highlightLines
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@ -1021,7 +1038,10 @@ const Editor = (props: PropTypes): JSX.Element => {
|
|||||||
|
|
||||||
// Protect against ranges that extend outside the editor
|
// Protect against ranges that extend outside the editor
|
||||||
const startLineNumber = Math.max(1, range.startLineNumber);
|
const startLineNumber = Math.max(1, range.startLineNumber);
|
||||||
const endLineNumber = Math.min(model?.getLineCount(), range.endLineNumber);
|
const endLineNumber = Math.min(
|
||||||
|
model?.getLineCount(),
|
||||||
|
range.endLineNumber
|
||||||
|
);
|
||||||
const endColumnText = model.getLineContent(endLineNumber);
|
const endColumnText = model.getLineContent(endLineNumber);
|
||||||
// NOTE: the end column is incremented by 2 so that the dangerous range
|
// NOTE: the end column is incremented by 2 so that the dangerous range
|
||||||
// extends far enough to capture new text added to the end.
|
// extends far enough to capture new text added to the end.
|
||||||
@ -1150,17 +1170,19 @@ const Editor = (props: PropTypes): JSX.Element => {
|
|||||||
editorWillMount={editorWillMount}
|
editorWillMount={editorWillMount}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
options={options}
|
options={options}
|
||||||
|
ref={ref}
|
||||||
theme={editorTheme}
|
theme={editorTheme}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
);
|
||||||
|
|
||||||
Editor.displayName = 'Editor';
|
Editor.displayName = 'Editor';
|
||||||
|
|
||||||
// NOTE: withRef gets replaced by forwardRef in react-redux 6,
|
// NOTE: withRef gets replaced by forwardRef in react-redux 6,
|
||||||
// https://github.com/reduxjs/react-redux/releases/tag/v6.0.0
|
// https://github.com/reduxjs/react-redux/releases/tag/v6.0.0
|
||||||
export default connect(mapStateToProps, mapDispatchToProps, null, {
|
export default connect(mapStateToProps, mapDispatchToProps, null, {
|
||||||
forwardRef: true
|
withRef: true
|
||||||
})(Editor);
|
})(Editor);
|
||||||
|
@ -60,7 +60,7 @@ function Hotkeys({
|
|||||||
FOCUS_EDITOR: (e: React.KeyboardEvent) => {
|
FOCUS_EDITOR: (e: React.KeyboardEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (editorRef && editorRef.current) {
|
if (editorRef && editorRef.current) {
|
||||||
editorRef.current.getWrappedInstance().focusOnEditor();
|
editorRef.current.getWrappedInstance().editor.focus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
NAVIGATION_MODE: () => setEditorFocusability(false),
|
NAVIGATION_MODE: () => setEditorFocusability(false),
|
||||||
|
Reference in New Issue
Block a user