[MM-51302] Fix scroll to the bottom of editor after pasting long text (#22491)
Automatic Merge
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
62e6f29638
Коммит
9c4455d103
@@ -10,6 +10,8 @@
|
|||||||
// Stage: @prod
|
// Stage: @prod
|
||||||
// Group: @channels @collapsed_reply_threads
|
// Group: @channels @collapsed_reply_threads
|
||||||
|
|
||||||
|
import * as TIMEOUTS from '../../../fixtures/timeouts';
|
||||||
|
|
||||||
describe('Collapsed Reply Threads', () => {
|
describe('Collapsed Reply Threads', () => {
|
||||||
let testTeam;
|
let testTeam;
|
||||||
let testUser;
|
let testUser;
|
||||||
@@ -174,4 +176,45 @@ describe('Collapsed Reply Threads', () => {
|
|||||||
cy.uiCloseRHS();
|
cy.uiCloseRHS();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('MM-T5413 should auto-scroll to bottom upon pasting long text in reply', () => {
|
||||||
|
// # Post a root post as current user
|
||||||
|
cy.postMessageAs({
|
||||||
|
sender: testUser,
|
||||||
|
message: 'Another interesting post,',
|
||||||
|
channelId: testChannel.id,
|
||||||
|
}).then(({id: rootId}) => {
|
||||||
|
// # Post multiple replies as other user so that the new messages line is pushed up
|
||||||
|
Cypress._.times(20, (i) => {
|
||||||
|
cy.postMessageAs({
|
||||||
|
sender: otherUser,
|
||||||
|
message: 'Reply ' + i,
|
||||||
|
channelId: testChannel.id,
|
||||||
|
rootId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// # Click root post
|
||||||
|
cy.get(`#post_${rootId}`).click();
|
||||||
|
|
||||||
|
// # Wait for RHS to open and scroll to position
|
||||||
|
cy.wait(TIMEOUTS.ONE_SEC);
|
||||||
|
|
||||||
|
// * RHS should open and the editor's actions should not be visible.
|
||||||
|
cy.get('#rhsContainer').findByTestId('SendMessageButton').should('not.be.visible');
|
||||||
|
|
||||||
|
// # Close RHS
|
||||||
|
cy.uiCloseRHS();
|
||||||
|
|
||||||
|
// # Click root post
|
||||||
|
cy.get(`#post_${rootId}`).click();
|
||||||
|
|
||||||
|
// # Paste a multiline string in the RHS textbox.
|
||||||
|
const text = 'word '.repeat(2000);
|
||||||
|
cy.get('#rhsContainer').findByTestId('reply_textbox').clear().invoke('val', text).trigger('input');
|
||||||
|
|
||||||
|
// * RHS should open and the editor should be visible and focused
|
||||||
|
cy.get('#rhsContainer').findByTestId('SendMessageButton').should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ const AdvanceTextEditor = ({
|
|||||||
canUploadFiles,
|
canUploadFiles,
|
||||||
enableEmojiPicker,
|
enableEmojiPicker,
|
||||||
enableGifPicker,
|
enableGifPicker,
|
||||||
handleBlur,
|
handleBlur: onBlur,
|
||||||
handlePostError,
|
handlePostError,
|
||||||
emitTypingEvent,
|
emitTypingEvent,
|
||||||
handleMouseUpKeyUp,
|
handleMouseUpKeyUp,
|
||||||
@@ -170,6 +170,7 @@ const AdvanceTextEditor = ({
|
|||||||
const [scrollbarWidth, setScrollbarWidth] = useState(0);
|
const [scrollbarWidth, setScrollbarWidth] = useState(0);
|
||||||
const [renderScrollbar, setRenderScrollbar] = useState(false);
|
const [renderScrollbar, setRenderScrollbar] = useState(false);
|
||||||
const [showFormattingSpacer, setShowFormattingSpacer] = useState(shouldShowPreview);
|
const [showFormattingSpacer, setShowFormattingSpacer] = useState(shouldShowPreview);
|
||||||
|
const [keepEditorInFocus, setKeepEditorInFocus] = useState(false);
|
||||||
|
|
||||||
const input = textboxRef.current?.getInputBox();
|
const input = textboxRef.current?.getInputBox();
|
||||||
|
|
||||||
@@ -187,6 +188,15 @@ const AdvanceTextEditor = ({
|
|||||||
setShowPreview(!shouldShowPreview);
|
setShowPreview(!shouldShowPreview);
|
||||||
}, [shouldShowPreview, setShowPreview]);
|
}, [shouldShowPreview, setShowPreview]);
|
||||||
|
|
||||||
|
const handleBlur = useCallback(() => {
|
||||||
|
onBlur?.();
|
||||||
|
setKeepEditorInFocus(false);
|
||||||
|
}, [onBlur]);
|
||||||
|
|
||||||
|
const handleFocus = useCallback(() => {
|
||||||
|
setKeepEditorInFocus(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
let serverErrorJsx = null;
|
let serverErrorJsx = null;
|
||||||
if (serverError) {
|
if (serverError) {
|
||||||
serverErrorJsx = (
|
serverErrorJsx = (
|
||||||
@@ -422,6 +432,7 @@ const AdvanceTextEditor = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
slot2={null}
|
slot2={null}
|
||||||
|
shouldScrollIntoView={keepEditorInFocus}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -479,6 +490,7 @@ const AdvanceTextEditor = ({
|
|||||||
handlePostError={handlePostError}
|
handlePostError={handlePostError}
|
||||||
value={messageValue}
|
value={messageValue}
|
||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
|
onFocus={handleFocus}
|
||||||
emojiEnabled={enableEmojiPicker}
|
emojiEnabled={enableEmojiPicker}
|
||||||
createMessage={createMessage}
|
createMessage={createMessage}
|
||||||
channelId={channelId}
|
channelId={channelId}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export type Props = {
|
|||||||
onMouseUp?: (e: React.MouseEvent<TextboxElement>) => void;
|
onMouseUp?: (e: React.MouseEvent<TextboxElement>) => void;
|
||||||
onKeyUp?: (e: React.KeyboardEvent<TextboxElement>) => void;
|
onKeyUp?: (e: React.KeyboardEvent<TextboxElement>) => void;
|
||||||
onBlur?: (e: FocusEvent<TextboxElement>) => void;
|
onBlur?: (e: FocusEvent<TextboxElement>) => void;
|
||||||
|
onFocus?: (e: FocusEvent<TextboxElement>) => void;
|
||||||
supportsCommands?: boolean;
|
supportsCommands?: boolean;
|
||||||
handlePostError?: (message: JSX.Element | null) => void;
|
handlePostError?: (message: JSX.Element | null) => void;
|
||||||
onPaste?: (e: ClipboardEvent) => void;
|
onPaste?: (e: ClipboardEvent) => void;
|
||||||
@@ -312,6 +313,7 @@ export default class Textbox extends React.PureComponent<Props> {
|
|||||||
onKeyUp={this.handleKeyUp}
|
onKeyUp={this.handleKeyUp}
|
||||||
onComposition={this.props.onComposition}
|
onComposition={this.props.onComposition}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
|
onFocus={this.props.onFocus}
|
||||||
onHeightChange={this.props.onHeightChange}
|
onHeightChange={this.props.onHeightChange}
|
||||||
onWidthChange={this.props.onWidthChange}
|
onWidthChange={this.props.onWidthChange}
|
||||||
onPaste={this.props.onPaste}
|
onPaste={this.props.onPaste}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user