[MM-65186] Keyboard focus is wrong when using Shift-Up to reply in thread (#34627) (#34697)

(cherry picked from commit 4fb41f3ba274f32b8e23f52e46b82e3d93f63af6)

Co-authored-by: M-ZubairAhmed <m-zubairahmed@protonmail.com>
Этот коммит содержится в:
Mattermost Build
2025-12-10 07:17:54 +02:00
коммит произвёл GitHub
родитель b3d6c0c564
Коммит f9fb13c7e6
4 изменённых файлов: 26 добавлений и 10 удалений

Просмотреть файл

@@ -11,7 +11,7 @@
// Group: @channels @keyboard_shortcuts
import * as messages from '../../../fixtures/messages';
import * as TIMEOUTS from '../../../fixtures/timeouts';
import timeouts, * as TIMEOUTS from '../../../fixtures/timeouts';
describe('Keyboard Shortcuts', () => {
let testTeam;
@@ -377,6 +377,7 @@ describe('Keyboard Shortcuts', () => {
cy.get('body').cmdOrCtrlShortcut('{shift}L');
cy.uiGetPostTextBox().should('be.focused');
cy.get('[data-testid="searchBoxClose"] > .icon').click();
// # Post a message and open RHS
const message = `hello${Date.now()}`;
cy.postMessage(message);
@@ -386,6 +387,7 @@ describe('Keyboard Shortcuts', () => {
cy.uiGetReplyTextBox().focus().should('be.focused');
}).then(() => {
// # Type CTRL/CMD+SHIFT+L
cy.wait(timeouts.ONE_SEC);
cy.get('body').cmdOrCtrlShortcut('{shift}L');
cy.uiGetPostTextBox().should('be.focused');
});

Просмотреть файл

@@ -2,7 +2,7 @@
// See LICENSE.txt for license information.
import type React from 'react';
import {useCallback, useEffect} from 'react';
import {useCallback, useEffect, useRef} from 'react';
import {useDispatch, useSelector} from 'react-redux';
import {focusedRHS} from 'actions/views/rhs';
@@ -23,11 +23,10 @@ const useTextboxFocus = (
) => {
const dispatch = useDispatch();
const hasMounted = useRef(false);
const rhsExpanded = useSelector(getIsRhsExpanded);
const rhsOpen = useSelector(getIsRhsOpen);
// We force the selector to always think it is the same value to avoid re-renders
// because we only use this value during mount.
const shouldFocusRHS = useSelector(getShouldFocusRHS, () => true);
const focusTextbox = useCallback((keepFocus = false) => {
@@ -48,7 +47,7 @@ const useTextboxFocus = (
textboxRef.current?.focus();
});
}
}, [canPost, textboxRef]);
}, [canPost]);
const focusTextboxIfNecessary = useCallback((e: KeyboardEvent) => {
// Do not focus if the rhs is expanded and this is not the RHS
@@ -91,15 +90,24 @@ const useTextboxFocus = (
focusTextbox();
}, [channelId]);
// Focus on mount
useEffect(() => {
if (isRHS && shouldFocusRHS) {
// If we are in the RHS and we are supposed to focus the RHS because of a reply,
// we focus the textbox and reset the shouldFocusRHS flag.
focusTextbox();
dispatch(focusedRHS());
} else if (!isRHS && !shouldFocusRHS) {
} else if (!isRHS && !shouldFocusRHS && !hasMounted.current) {
// If we are in the Center channel and we are not supposed to focus the RHS,
// we focus the textbox but only on mount.
// This is because if we focus on updates, we might steal focus from the RHS
// when the RHS focuses and resets the shouldFocusRHS flag.
focusTextbox();
}
}, []);
if (!hasMounted.current) {
hasMounted.current = true;
}
}, [isRHS, shouldFocusRHS, focusTextbox, dispatch]);
return focusTextbox;
};

Просмотреть файл

@@ -160,6 +160,12 @@ export default class SidebarRight extends React.PureComponent<Props, State> {
if (this.props.isOpen && (contentChanged || (!wasOpen && isOpen))) {
this.previousActiveElement = document.activeElement as HTMLElement;
// For RHS with textbox, don't auto-focus the first element with this approach.
// The RHS textbox will focus itself via use_textbox_focus.tsx hook with correct focus logic.
if (this.props.postRightVisible) {
return;
}
// Focus the sidebar after a tick
setTimeout(() => {
if (this.sidebarRight.current) {

Просмотреть файл

@@ -105,7 +105,7 @@ export function isMobileApp(): boolean {
return isMobile() && !isIosWeb() && !isAndroidWeb();
}
// Returns true if and only if the user is using Mattermost from either the mobile app or the web browser on a mobile device.
// Returns true if and only if the user is using Mattermost from the web browser on a mobile device.
export function isMobile(): boolean {
return isIos() || isAndroid();
}