diff --git a/.changeset/large-vans-attack.md b/.changeset/large-vans-attack.md new file mode 100644 index 000000000000..c1008b2ca06f --- /dev/null +++ b/.changeset/large-vans-attack.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +fixed the contextual bar closing when editing thread messages instead of cancelling the message edit diff --git a/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx b/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx index 4b7a466d6de0..00d9c66a2046 100644 --- a/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx +++ b/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx @@ -14,15 +14,7 @@ import { } from '@rocket.chat/ui-composer'; import { useTranslation, useUserPreference, useLayout, useSetting } from '@rocket.chat/ui-contexts'; import { useMutation } from '@tanstack/react-query'; -import type { - ReactElement, - MouseEventHandler, - FormEvent, - KeyboardEventHandler, - KeyboardEvent, - ClipboardEventHandler, - MouseEvent, -} from 'react'; +import type { ReactElement, MouseEventHandler, FormEvent, ClipboardEventHandler, MouseEvent } from 'react'; import React, { memo, useRef, useReducer, useCallback } from 'react'; import { Trans } from 'react-i18next'; import { useSubscription } from 'use-subscription'; @@ -60,11 +52,7 @@ const reducer = (_: unknown, event: FormEvent): boolean => { return Boolean(target.value.trim()); }; -const handleFormattingShortcut = ( - event: KeyboardEvent, - formattingButtons: FormattingButton[], - composer: ComposerAPI, -) => { +const handleFormattingShortcut = (event: KeyboardEvent, formattingButtons: FormattingButton[], composer: ComposerAPI) => { const isMacOS = navigator.platform.indexOf('Mac') !== -1; const isCmdOrCtrlPressed = (isMacOS && event.metaKey) || (!isMacOS && event.ctrlKey); @@ -196,7 +184,7 @@ const MessageBox = ({ } }; - const handler: KeyboardEventHandler = useMutableCallback((event) => { + const handler = useMutableCallback((event: KeyboardEvent) => { const { which: keyCode } = event; const input = event.target as HTMLTextAreaElement; @@ -357,7 +345,19 @@ const MessageBox = ({ configurations: composerPopupConfig, }); - const mergedRefs = useMessageComposerMergedRefs(c, textareaRef, callbackRef, autofocusRef); + const keyDownHandlerCallbackRef = useCallback( + (node: HTMLTextAreaElement) => { + if (node === null) { + return; + } + node.addEventListener('keydown', (e: KeyboardEvent) => { + handler(e); + }); + }, + [handler], + ); + + const mergedRefs = useMessageComposerMergedRefs(c, textareaRef, callbackRef, autofocusRef, keyDownHandlerCallbackRef); const shouldPopupPreview = useEnablePopupPreview(filter, popup); @@ -411,7 +411,6 @@ const MessageBox = ({ onChange={setTyping} style={textAreaStyle} placeholder={composerPlaceholder} - onKeyDown={handler} onPaste={handlePaste} aria-activedescendant={ariaActiveDescendant} /> diff --git a/apps/meteor/tests/e2e/threads.spec.ts b/apps/meteor/tests/e2e/threads.spec.ts index 16198c15a942..2de7c53ba48a 100644 --- a/apps/meteor/tests/e2e/threads.spec.ts +++ b/apps/meteor/tests/e2e/threads.spec.ts @@ -162,5 +162,38 @@ test.describe.serial('Threads', () => { await page.keyboard.press('Escape'); await expect(page).not.toHaveURL(/.*thread/); }); + + test('expect reset the thread composer to original message if user presses escape', async ({ page }) => { + await expect(page).toHaveURL(/.*thread/); + await expect(page.getByRole('dialog').locator('[data-qa-type="message"]')).toBeVisible(); + + await expect(page.locator('[name="msg"]').last()).toBeFocused(); + await page.locator('[name="msg"]').last().fill('message to be edited'); + await page.keyboard.press('Enter'); + await page.keyboard.press('ArrowUp'); + + await expect(page.locator('[name="msg"]').last()).toHaveValue('message to be edited'); + await page.locator('[name="msg"]').last().fill('this message was edited'); + + await page.keyboard.press('Escape'); + await expect(page.locator('[name="msg"]').last()).toHaveValue('message to be edited'); + await expect(page).toHaveURL(/.*thread/); + }); + + test('expect clean composer and keep the thread open if user is editing message and presses escape', async ({ page }) => { + await expect(page).toHaveURL(/.*thread/); + await expect(page.getByRole('dialog').locator('[data-qa-type="message"]')).toBeVisible(); + await expect(page.locator('[name="msg"]').last()).toBeFocused(); + + await page.locator('[name="msg"]').last().fill('message to be edited'); + await page.keyboard.press('Enter'); + + await page.keyboard.press('ArrowUp'); + await expect(page.locator('[name="msg"]').last()).toHaveValue('message to be edited'); + + await page.keyboard.press('Escape'); + await expect(page.locator('[name="msg"]').last()).toHaveValue(''); + await expect(page).toHaveURL(/.*thread/); + }); }); });