Skip to content

Commit

Permalink
[MM-42443]: fix selectionRange updates in edit_post component (matter…
Browse files Browse the repository at this point in the history
…most#10035)

* fixed setting selections with handling selectionRanges after state updates

* adjusted waiting time on e2e test for aborting message edit in main channel view

* fixed some errors after merging master

* increased wait times for MM-T2139

* fix flaky MM-T2139

Co-authored-by: Mattermod <[email protected]>
Co-authored-by: Saturnino Abril <[email protected]>
  • Loading branch information
3 people authored and Willyfrog committed May 6, 2022
1 parent 5e01c5a commit 079dab7
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 40 deletions.
56 changes: 24 additions & 32 deletions components/edit_post/edit_post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export type Props = {

export type State = {
editText: string;
caretPosition: number;
selectionRange: {start: number; end: number};
postError: React.ReactNode;
errorClass: string | null;
showEmojiPicker: boolean;
Expand All @@ -82,7 +82,7 @@ const EditPost = ({editingPost, actions, ...rest}: Props): JSX.Element | null =>
const [editText, setEditText] = useState<string>(
editingPost?.post?.message_source || editingPost?.post?.message || '',
);
const [caretPosition, setCaretPosition] = useState<number>(editText.length);
const [selectionRange, setSelectionRange] = useState<State['selectionRange']>({start: editText.length, end: editText.length});
const [postError, setPostError] = useState<React.ReactNode | null>(null);
const [errorClass, setErrorClass] = useState<string>('');
const [showEmojiPicker, setShowEmojiPicker] = useState<boolean>(false);
Expand All @@ -101,47 +101,53 @@ const EditPost = ({editingPost, actions, ...rest}: Props): JSX.Element | null =>
return () => document.removeEventListener(AppEvents.FOCUS_EDIT_TEXTBOX, focusTextBox);
}, []);

const handlePaste: ClipboardEventHandler<HTMLInputElement> = (e) => {
useEffect(() => {
if (selectionRange.start === selectionRange.end) {
Utils.setCaretPosition(textboxRef.current?.getInputBox(), selectionRange.start);
} else {
Utils.setSelectionRange(textboxRef.current?.getInputBox(), selectionRange.start, selectionRange.end);
}
}, [selectionRange]);

// just a helper so it's not always needed to update with setting both properties to the same value
const setCaretPosition = (position: number) => setSelectionRange({start: position, end: position});

const handlePaste: ClipboardEventHandler<HTMLTextAreaElement> = ({clipboardData, target, preventDefault}) => {
if (
!e.clipboardData ||
!e.clipboardData.items ||
!clipboardData ||
!clipboardData.items ||
!rest.canEditPost ||
(e.target as HTMLTextAreaElement).id !== 'edit_textbox'
(target as HTMLTextAreaElement).id !== 'edit_textbox'
) {
return;
}

const {clipboardData} = e;
const table = getTable(clipboardData);

if (!table) {
return;
}

e.preventDefault();
preventDefault();

let message = editText;
let newCaretPosition = caretPosition;
let newCaretPosition = selectionRange.start;

if (table && isGitHubCodeBlock(table.className)) {
const {formattedMessage, formattedCodeBlock} = formatGithubCodePaste(
caretPosition,
selectionRange.start,
message,
clipboardData,
);
message = formattedMessage;
newCaretPosition = caretPosition + formattedCodeBlock.length;
newCaretPosition = selectionRange.start + formattedCodeBlock.length;
} else if (table) {
message = formatMarkdownTableMessage(table, editText.trim(), newCaretPosition);
newCaretPosition = message.length - (editText.length - newCaretPosition);
}

setEditText(message);
setCaretPosition(newCaretPosition);

if (textboxRef.current) {
Utils.setCaretPosition(textboxRef.current.getInputBox(), newCaretPosition);
}
};

const isSaveDisabled = () => {
Expand All @@ -163,13 +169,7 @@ const EditPost = ({editingPost, actions, ...rest}: Props): JSX.Element | null =>
const res = Utils.applyHotkeyMarkdown(e);

setEditText(res.message);
if (textboxRef.current) {
Utils.setSelectionRange(
textboxRef.current.getInputBox(),
res.selectionStart,
res.selectionEnd,
);
}
setSelectionRange({start: res.selectionStart, end: res.selectionEnd});
};

const handleRefocusAndExit = (refocusId: string|null) => {
Expand Down Expand Up @@ -237,7 +237,7 @@ const EditPost = ({editingPost, actions, ...rest}: Props): JSX.Element | null =>
codeBlockOnCtrlEnter,
Date.now(),
0,
caretPosition,
selectionRange.start,
);

if (ignoreKeyPress) {
Expand Down Expand Up @@ -286,9 +286,6 @@ const EditPost = ({editingPost, actions, ...rest}: Props): JSX.Element | null =>
}
};

const handleMouseUpKeyUp = (e: React.MouseEvent | React.KeyboardEvent) =>
setCaretPosition(Utils.getCaretPosition(e.target as HTMLElement));

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => setEditText(e.target.value);

const handleHeightChange = (height: number, maxHeight: number) => setRenderScrollbar(height > maxHeight);
Expand Down Expand Up @@ -316,7 +313,7 @@ const EditPost = ({editingPost, actions, ...rest}: Props): JSX.Element | null =>
setEditText(`:${emojiAlias}: `);
} else {
const {firstPiece, lastPiece} = splitMessageBasedOnCaretPosition(
caretPosition,
selectionRange.start,
editText,
);

Expand All @@ -325,11 +322,8 @@ const EditPost = ({editingPost, actions, ...rest}: Props): JSX.Element | null =>
const newMessage = firstPiece === '' ? `:${emojiAlias}: ${lastPiece}` : `${firstPiece} :${emojiAlias}: ${lastPiece}`;
const newCaretPosition = firstPiece === '' ? `:${emojiAlias}: `.length : `${firstPiece} :${emojiAlias}: `.length;

const textbox = textboxRef.current?.getInputBox();

setEditText(newMessage);
setCaretPosition(newCaretPosition);
Utils.setCaretPosition(textbox, newCaretPosition);
}

setShowEmojiPicker(false);
Expand Down Expand Up @@ -407,8 +401,6 @@ const EditPost = ({editingPost, actions, ...rest}: Props): JSX.Element | null =>
onKeyPress={handleEditKeyPress}
onKeyDown={handleKeyDown}
onSelect={handleSelect}
onMouseUp={handleMouseUpKeyUp}
onKeyUp={handleMouseUpKeyUp}
onHeightChange={handleHeightChange}
handlePostError={handlePostError}
onPaste={handlePaste}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -483,20 +483,20 @@ describe('Messaging', () => {

it('MM-T2139 Canceling out of editing a message makes no changes - Center', () => {
// # Post message
cy.get('#post_textbox').type(message1).type('{enter}').wait(TIMEOUTS.HALF_SEC);
cy.postMessage(message1);

// # Edit post containing channel link
cy.getLastPostId().then((postId) => {
cy.clickPostDotMenu(postId);
// # Click 'Edit' to last post
cy.uiClickPostDropdownMenu(postId, 'Edit');

// * Click edit post
cy.get(`#edit_post_${postId}`).scrollIntoView().should('be.visible').click();
cy.get('#edit_textbox').should('be.visible');
// * Edit textbox should be visible
cy.get('#edit_textbox').should('be.visible').wait(TIMEOUTS.ONE_SEC);

// * Close the input
// # Make no change then press enter
cy.get('#edit_textbox').type('{enter}');

// # Verify that last post does not contain "Edited"
// # Verify that edit textbox no longer exist and last post does not contain "Edited"
cy.get('#edit_textbox').should('not.exist');
cy.get(`#postMessageText_${postId}`).should('contain', message1).and('not.contain', 'Edited');
});
});
Expand Down
4 changes: 4 additions & 0 deletions utils/utils.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -957,6 +957,10 @@ export function setSelectionRange(input, selectionStart, selectionEnd) {
}

export function setCaretPosition(input, pos) {
if (!input) {
return;
}

setSelectionRange(input, pos, pos);
}

Expand Down

0 comments on commit 079dab7

Please sign in to comment.