Skip to content

Commit

Permalink
fix(reply): Fix editor focus causes jumping to page top (#487)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mingze authored May 18, 2020
1 parent 619e7be commit bbed3f4
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 42 deletions.
43 changes: 17 additions & 26 deletions src/components/Popups/ReplyField/ReplyField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,33 +45,16 @@ export default class ReplyField extends React.Component<Props, State> {
value: '',
};

editorRef: React.MutableRefObject<Editor | null> = React.createRef<Editor | null>();

constructor(props: Props) {
super(props);

const { value, cursorPosition } = props;
const contentState = ContentState.createFromText(value as string);
let prevEditorState = withMentionDecorator(EditorState.createWithContent(contentState));
let selectionState = prevEditorState.getSelection();

selectionState = selectionState.merge({
anchorOffset: cursorPosition,
focusOffset: cursorPosition,
}) as SelectionState;
prevEditorState = EditorState.forceSelection(prevEditorState, selectionState);

this.state = {
activeItemIndex: 0,
editorState: prevEditorState,
editorState: this.restoreEditor(),
popupReference: null,
};
}

componentDidMount(): void {
this.focusEditor();
}

componentWillUnmount(): void {
this.saveCursorPosition();
}
Expand Down Expand Up @@ -140,13 +123,6 @@ export default class ReplyField extends React.Component<Props, State> {
this.setState({ popupReference: activeMention ? this.getVirtualElement(activeMention) : null });
};

focusEditor = (): void => {
const { current: editor } = this.editorRef;
if (editor) {
editor.focus();
}
};

saveCursorPosition = (): void => {
const { setCursorPosition } = this.props;
const { editorState } = this.state;
Expand Down Expand Up @@ -230,6 +206,22 @@ export default class ReplyField extends React.Component<Props, State> {
this.setPopupListActiveItem(activeItemIndex === length - 1 ? 0 : activeItemIndex + 1);
};

restoreEditor(): EditorState {
const { cursorPosition: prevCursorPosition, value } = this.props;
const contentState = ContentState.createFromText(value as string);
const prevEditorState = withMentionDecorator(EditorState.createWithContent(contentState));
const cursorPosition = value ? prevCursorPosition : 0;

return EditorState.forceSelection(
prevEditorState,
prevEditorState.getSelection().merge({
anchorOffset: cursorPosition,
focusOffset: cursorPosition,
hasFocus: true,
}) as SelectionState,
);
}

render(): JSX.Element {
const { className, isDisabled, itemRowAs, placeholder, ...rest } = this.props;
const { activeItemIndex, editorState, popupReference } = this.state;
Expand All @@ -238,7 +230,6 @@ export default class ReplyField extends React.Component<Props, State> {
<div className={classnames(className, 'ba-ReplyField')}>
<Editor
{...rest}
ref={this.editorRef}
editorState={editorState}
handleReturn={this.handleReturn}
onChange={this.handleChange}
Expand Down
34 changes: 18 additions & 16 deletions src/components/Popups/ReplyField/__tests__/ReplyField-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,24 @@ describe('components/Popups/ReplyField', () => {
const getWrapper = (props = {}): ShallowWrapper<Props, State, ReplyField> =>
shallow(<ReplyField {...defaults} {...props} />);

describe('restoreEditor()', () => {
test('should restore value and cursor position', () => {
const wrapper = getWrapper({ cursorPosition: 1, value: 'test' });

const editorState = wrapper.instance().restoreEditor();

expect(editorState.getCurrentContent().getPlainText()).toEqual('test');
expect(editorState.getSelection().getFocusOffset()).toEqual(1);
});

test('should reset cursor position if value is empty', () => {
const wrapper = getWrapper({ cursorPosition: 1 });
const editorState = wrapper.instance().restoreEditor();

expect(editorState.getSelection().getFocusOffset()).toEqual(0);
});
});

describe('render()', () => {
test('should render the editor with right props', () => {
const wrapper = getWrapper();
Expand Down Expand Up @@ -238,22 +256,6 @@ describe('components/Popups/ReplyField', () => {
});
});

describe('focusEditor()', () => {
test('should call editor ref focus', () => {
const wrapper = getWrapper();
const instance = wrapper.instance();

const editorRef = ({
focus: jest.fn(),
} as unknown) as Editor;

instance.editorRef = { current: editorRef };
instance.focusEditor();

expect(editorRef.focus).toBeCalled();
});
});

describe('saveCursorPosition()', () => {
test('should call setCursorPosition with cursor position', () => {
const wrapper = getWrapper();
Expand Down

0 comments on commit bbed3f4

Please sign in to comment.