Thread reply edit file handling bug fix (#30470)

* Fixed a bug where escape would delete all typed content

* Fixed rootId and postID

* fixed tests

* Type fix

* Fixed a test

* Search result edit fix

* Removed a test change

* threads view isn't RHS

* Fixed a cypress test

* Fixed a cypress test

* Fixed a flaky playwighr test
Этот коммит содержится в:
Harshil Sharma
2025-03-18 16:19:18 +05:30
коммит произвёл GitHub
родитель c1d4f5cb9f
Коммит c951a9cfac
13 изменённых файлов: 78 добавлений и 76 удалений

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

@@ -302,7 +302,10 @@ describe('Keyboard Shortcuts', () => {
cy.uiGetPostTextBox().type('{uparrow}'); cy.uiGetPostTextBox().type('{uparrow}');
// # Add some text to the previous message and save // # Add some text to the previous message and save
cy.get('#edit_textbox').type('Test').type('{enter}'); // cy.get('#edit_textbox').type('Test').type('{enter}');
cy.get('#edit_textbox').type('Test');
cy.wait(TIMEOUTS.ONE_SEC);
cy.get('#edit_textbox').type('{enter}');
cy.wait(TIMEOUTS.ONE_SEC); cy.wait(TIMEOUTS.ONE_SEC);
cy.getLastPost().within(() => { cy.getLastPost().within(() => {

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

@@ -732,7 +732,7 @@ describe('Messaging', () => {
cy.get('#edit_textbox').should('be.visible'); cy.get('#edit_textbox').should('be.visible');
// * Update the post message and type ENTER // * Update the post message and type ENTER
cy.get('#edit_textbox', {timeout: TIMEOUTS.FIVE_SEC}).invoke('val', '').type(message2).type('{enter}').wait(TIMEOUTS.HALF_SEC); cy.get('#edit_textbox', {timeout: TIMEOUTS.FIVE_SEC}).invoke('val', '').type(message2).wait(TIMEOUTS.HALF_SEC).type('{enter}').wait(TIMEOUTS.HALF_SEC);
// * Post appears in RHS search results, displays Pinned badge // * Post appears in RHS search results, displays Pinned badge
cy.get(`#searchResult_${postId}`).findByText('Edited').should('exist'); cy.get(`#searchResult_${postId}`).findByText('Edited').should('exist');

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

@@ -3,6 +3,7 @@
import {expect, Locator} from '@playwright/test'; import {expect, Locator} from '@playwright/test';
import path from 'node:path'; import path from 'node:path';
import {waitUntil} from '@e2e-support/test_action';
export default class ChannelsPostCreate { export default class ChannelsPostCreate {
readonly container: Locator; readonly container: Locator;
@@ -106,6 +107,12 @@ export default class ChannelsPostCreate {
}); });
await this.attachmentButton.click(); await this.attachmentButton.click();
// wait for all files to be uploaded
await waitUntil(async () => {
const attachment = await this.container.locator('.file-preview').count();
return attachment === files.length;
});
} }
await this.sendMessage(); await this.sendMessage();

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

@@ -39,7 +39,7 @@ const AdvancedCreateComment = ({
<AdvancedTextEditor <AdvancedTextEditor
location={Locations.RHS_COMMENT} location={Locations.RHS_COMMENT}
channelId={channelId} channelId={channelId}
postId={rootId} rootId={rootId}
isThreadView={isThreadView} isThreadView={isThreadView}
placeholder={placeholder} placeholder={placeholder}
afterSubmit={afterSubmit} afterSubmit={afterSubmit}

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

@@ -22,7 +22,7 @@ const AdvancedCreatePost = () => {
return ( return (
<AdvancedTextEditor <AdvancedTextEditor
location={Locations.CENTER} location={Locations.CENTER}
postId={''} rootId={''}
channelId={currentChannelId} channelId={currentChannelId}
/> />
); );

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

@@ -130,7 +130,7 @@ const baseProps = {
uploadsProgressPercent: {}, uploadsProgressPercent: {},
currentChannel: initialState.entities.channels.channels.current_channel_id as Channel, currentChannel: initialState.entities.channels.channels.current_channel_id as Channel,
channelId, channelId,
postId: '', rootId: '',
errorClass: null, errorClass: null,
serverError: null, serverError: null,
postError: null, postError: null,
@@ -421,7 +421,7 @@ describe('components/avanced_text_editor/advanced_text_editor', () => {
it('should show @mention warning when a mention exists in the message', () => { it('should show @mention warning when a mention exists in the message', () => {
const props = { const props = {
...baseProps, ...baseProps,
postId: 'post_id_1', rootId: 'post_id_1',
isInEditMode: true, isInEditMode: true,
}; };
@@ -457,7 +457,7 @@ describe('components/avanced_text_editor/advanced_text_editor', () => {
); );
expect(container.querySelector('#createPostFileDropOverlay')).toBeVisible(); expect(container.querySelector('#createPostFileDropOverlay')).toBeVisible();
props.postId = 'post_id_1'; props.rootId = 'post_id_1';
rerender(<AdvancedTextEditor {...props}/>); rerender(<AdvancedTextEditor {...props}/>);
expect(container.querySelector('#createCommentFileDropOverlay')).toBeVisible(); expect(container.querySelector('#createCommentFileDropOverlay')).toBeVisible();

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

@@ -9,11 +9,9 @@ import {useDispatch, useSelector} from 'react-redux';
import type {ServerError} from '@mattermost/types/errors'; import type {ServerError} from '@mattermost/types/errors';
import type {SchedulingInfo} from '@mattermost/types/schedule_post'; import type {SchedulingInfo} from '@mattermost/types/schedule_post';
import {FileTypes} from 'mattermost-redux/action_types';
import {savePreferences} from 'mattermost-redux/actions/preferences'; import {savePreferences} from 'mattermost-redux/actions/preferences';
import {Permissions} from 'mattermost-redux/constants'; import {Permissions} from 'mattermost-redux/constants';
import {getChannel, makeGetChannel, getDirectChannel} from 'mattermost-redux/selectors/entities/channels'; import {getChannel, makeGetChannel, getDirectChannel} from 'mattermost-redux/selectors/entities/channels';
import {getFilesIdsForPost} from 'mattermost-redux/selectors/entities/files';
import {getConfig, getFeatureFlagValue} from 'mattermost-redux/selectors/entities/general'; import {getConfig, getFeatureFlagValue} from 'mattermost-redux/selectors/entities/general';
import {get, getBool, getInt} from 'mattermost-redux/selectors/entities/preferences'; import {get, getBool, getInt} from 'mattermost-redux/selectors/entities/preferences';
import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles'; import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles';
@@ -98,7 +96,8 @@ export type Props = {
*/ */
location: string; location: string;
channelId: string; channelId: string;
postId: string; rootId: string;
postId?: string;
isThreadView?: boolean; isThreadView?: boolean;
placeholder?: string; placeholder?: string;
isInEditMode?: boolean; isInEditMode?: boolean;
@@ -118,6 +117,7 @@ export type Props = {
const AdvancedTextEditor = ({ const AdvancedTextEditor = ({
location, location,
channelId, channelId,
rootId,
postId, postId,
isThreadView = false, isThreadView = false,
placeholder, placeholder,
@@ -146,7 +146,7 @@ const AdvancedTextEditor = ({
textboxId = AdvancedTextEditorTextboxIds.Default; textboxId = AdvancedTextEditorTextboxIds.Default;
} }
const isRHS = Boolean(postId && !isThreadView); const isRHS = isThreadView ? false : Boolean(rootId) || location === Locations.RHS_COMMENT;
const getFormattingBarPreferenceName = () => { const getFormattingBarPreferenceName = () => {
let name: string; let name: string;
@@ -164,7 +164,7 @@ const AdvancedTextEditor = ({
const channelDisplayName = channel?.display_name || ''; const channelDisplayName = channel?.display_name || '';
const channelType = channel?.type || ''; const channelType = channel?.type || '';
const isChannelShared = channel?.shared; const isChannelShared = channel?.shared;
const draftFromStore = useSelector((state: GlobalState) => getDraftSelector(state, channelId, postId, storageKey)); const draftFromStore = useSelector((state: GlobalState) => getDraftSelector(state, channelId, rootId, storageKey));
const badConnection = useSelector((state: GlobalState) => connectionErrorCount(state) > 1); const badConnection = useSelector((state: GlobalState) => connectionErrorCount(state) > 1);
const maxPostSize = useSelector((state: GlobalState) => parseInt(getConfig(state).MaxPostSize || '', 10) || Constants.DEFAULT_CHARACTER_LIMIT); const maxPostSize = useSelector((state: GlobalState) => parseInt(getConfig(state).MaxPostSize || '', 10) || Constants.DEFAULT_CHARACTER_LIMIT);
const canUploadFiles = useSelector((state: GlobalState) => canUploadFilesAccordingToConfig(getConfig(state))); const canUploadFiles = useSelector((state: GlobalState) => canUploadFilesAccordingToConfig(getConfig(state)));
@@ -188,7 +188,7 @@ const AdvancedTextEditor = ({
}); });
const showSendTutorialTip = useSelector((state: GlobalState) => { const showSendTutorialTip = useSelector((state: GlobalState) => {
// We don't show the tutorial tip neither on RHS nor Thread view // We don't show the tutorial tip neither on RHS nor Thread view
if (postId) { if (rootId) {
return false; return false;
} }
const config = getConfig(state); const config = getConfig(state);
@@ -202,7 +202,6 @@ const AdvancedTextEditor = ({
return enableTutorial && (tutorialStep === tourStep); return enableTutorial && (tutorialStep === tourStep);
}); });
const postFileIds = useSelector((state: GlobalState) => getFilesIdsForPost(state, postId));
const editorActionsRef = useRef<HTMLDivElement>(null); const editorActionsRef = useRef<HTMLDivElement>(null);
const editorBodyRef = useRef<HTMLDivElement>(null); const editorBodyRef = useRef<HTMLDivElement>(null);
@@ -235,8 +234,8 @@ const AdvancedTextEditor = ({
}, []); }, []);
const emitTypingEvent = useCallback(() => { const emitTypingEvent = useCallback(() => {
GlobalActions.emitLocalUserTypingEvent(channelId, postId); GlobalActions.emitLocalUserTypingEvent(channelId, rootId);
}, [channelId, postId]); }, [channelId, rootId]);
const handleDraftChange = useCallback((draftToChange: PostDraft, options: {instant?: boolean; show?: boolean} = {instant: false, show: false}) => { const handleDraftChange = useCallback((draftToChange: PostDraft, options: {instant?: boolean; show?: boolean} = {instant: false, show: false}) => {
if (saveDraftFrame.current) { if (saveDraftFrame.current) {
@@ -307,12 +306,12 @@ const AdvancedTextEditor = ({
}])); }]));
}, [dispatch, currentUserId, getFormattingBarPreferenceName, isFormattingBarHidden]); }, [dispatch, currentUserId, getFormattingBarPreferenceName, isFormattingBarHidden]);
useOrientationHandler(textboxRef, postId); useOrientationHandler(textboxRef, rootId);
const pluginItems = usePluginItems(draft, textboxRef, handleDraftChange); const pluginItems = usePluginItems(draft, textboxRef, handleDraftChange);
const focusTextbox = useTextboxFocus(textboxRef, channelId, isRHS, canPost); const focusTextbox = useTextboxFocus(textboxRef, channelId, isRHS, canPost);
const [attachmentPreview, fileUploadJSX] = useUploadFiles( const [attachmentPreview, fileUploadJSX] = useUploadFiles(
draft, draft,
postId, rootId,
channelId, channelId,
isThreadView, isThreadView,
storedDrafts, storedDrafts,
@@ -348,7 +347,7 @@ const AdvancedTextEditor = ({
draft, draft,
postError, postError,
channelId, channelId,
postId, rootId,
serverError, serverError,
lastBlurAt, lastBlurAt,
focusTextbox, focusTextbox,
@@ -360,6 +359,7 @@ const AdvancedTextEditor = ({
afterSubmit, afterSubmit,
undefined, undefined,
isInEditMode, isInEditMode,
postId,
); );
const handleSubmitWithErrorHandling = useCallback((submittingDraft?: PostDraft, schedulingInfo?: SchedulingInfo, options?: CreatePostOptions) => { const handleSubmitWithErrorHandling = useCallback((submittingDraft?: PostDraft, schedulingInfo?: SchedulingInfo, options?: CreatePostOptions) => {
@@ -383,30 +383,10 @@ const AdvancedTextEditor = ({
createAt: 0, createAt: 0,
updateAt: 0, updateAt: 0,
channelId, channelId,
rootId: postId, rootId,
metadata: {}, metadata: {},
}); });
}, [handleDraftChange, channelId, postId]); }, [handleDraftChange, channelId, rootId]);
const handleFileChangesOnSave = useCallback((draft: PostDraft) => {
// sets the updated data for file IDs by post ID part
dispatch({
type: FileTypes.RECEIVED_FILES_FOR_POST,
data: draft.fileInfos,
postId,
});
// removes the data for the deleted files from store
const deletedFileIds = postFileIds.filter((id: string) => !draft.fileInfos.find((file) => file.id === id));
if (deletedFileIds) {
dispatch({
type: FileTypes.REMOVED_FILE,
data: {
fileIds: deletedFileIds,
},
});
}
}, [dispatch, postFileIds, postId]);
const handleSubmitWrapper = useCallback(() => { const handleSubmitWrapper = useCallback(() => {
const isEmptyPost = isPostDraftEmpty(draft); const isEmptyPost = isPostDraftEmpty(draft);
@@ -425,17 +405,13 @@ const AdvancedTextEditor = ({
return; return;
} }
if (isInEditMode) {
handleFileChangesOnSave(draft);
}
handleSubmitWithErrorHandling(); handleSubmitWithErrorHandling();
}, [dispatch, draft, handleFileChangesOnSave, handleSubmitWithErrorHandling, isInEditMode, isRHS]); }, [dispatch, draft, handleSubmitWithErrorHandling, isInEditMode, isRHS]);
const [handleKeyDown, postMsgKeyPress] = useKeyHandler( const [handleKeyDown, postMsgKeyPress] = useKeyHandler(
draft, draft,
channelId, channelId,
postId, rootId,
caretPosition, caretPosition,
isValidPersistentNotifications, isValidPersistentNotifications,
location, location,
@@ -583,11 +559,11 @@ const AdvancedTextEditor = ({
useEffect(() => { useEffect(() => {
setShowPreview(false); setShowPreview(false);
setServerError(null); setServerError(null);
}, [channelId, postId]); }, [channelId, rootId]);
// Remove uploads in progress on mount // Remove uploads in progress on mount
useEffect(() => { useEffect(() => {
dispatch(actionOnGlobalItemsWithPrefix(postId ? StoragePrefixes.COMMENT_DRAFT : StoragePrefixes.DRAFT, (_key: string, draft: PostDraft) => { dispatch(actionOnGlobalItemsWithPrefix(rootId ? StoragePrefixes.COMMENT_DRAFT : StoragePrefixes.DRAFT, (_key: string, draft: PostDraft) => {
if (!draft || !draft.uploadsInProgress || draft.uploadsInProgress.length === 0) { if (!draft || !draft.uploadsInProgress || draft.uploadsInProgress.length === 0) {
return draft; return draft;
} }
@@ -626,7 +602,7 @@ const AdvancedTextEditor = ({
handleDraftChange(draftRef.current, {instant: true, show: true}); handleDraftChange(draftRef.current, {instant: true, show: true});
} }
}; };
}, [channelId, postId]); }, [channelId, rootId]);
const disableSendButton = Boolean(isDisabled || (!draft.message.trim().length && !draft.fileInfos.length)) || !isValidPersistentNotifications; const disableSendButton = Boolean(isDisabled || (!draft.message.trim().length && !draft.fileInfos.length)) || !isValidPersistentNotifications;
const sendButton = readOnlyChannel || isInEditMode ? null : ( const sendButton = readOnlyChannel || isInEditMode ? null : (
@@ -647,7 +623,7 @@ const AdvancedTextEditor = ({
let createMessage; let createMessage;
if (placeholder) { if (placeholder) {
createMessage = placeholder; createMessage = placeholder;
} else if (!postId && !isDisabled) { } else if (!rootId && !isDisabled) {
createMessage = formatMessage( createMessage = formatMessage(
{ {
id: 'create_post.write', id: 'create_post.write',
@@ -750,9 +726,9 @@ const AdvancedTextEditor = ({
return ( return (
<form <form
id={postId ? undefined : 'create_post'} id={rootId ? undefined : 'create_post'}
data-testid={postId ? undefined : 'create-post'} data-testid={rootId ? undefined : 'create-post'}
className={(!postId && !fullWidthTextBox) ? 'center' : undefined} className={(!rootId && !fullWidthTextBox) ? 'center' : undefined}
onSubmit={handleSubmitWithEvent} onSubmit={handleSubmitWithEvent}
> >
{canPost && (draft.fileInfos.length > 0 || draft.uploadsInProgress.length > 0) && ( {canPost && (draft.fileInfos.length > 0 || draft.uploadsInProgress.length > 0) && (
@@ -764,7 +740,7 @@ const AdvancedTextEditor = ({
channelId={channelId} channelId={channelId}
teammateDisplayName={teammateDisplayName} teammateDisplayName={teammateDisplayName}
location={location} location={location}
postId={postId} postId={rootId}
/> />
)} )}
<div <div
@@ -824,7 +800,7 @@ const AdvancedTextEditor = ({
preview={showPreview} preview={showPreview}
badConnection={badConnection} badConnection={badConnection}
useChannelMentions={useChannelMentions} useChannelMentions={useChannelMentions}
rootId={postId} rootId={rootId}
onWidthChange={handleWidthChange} onWidthChange={handleWidthChange}
isInEditMode={isInEditMode} isInEditMode={isInEditMode}
/> />
@@ -876,7 +852,7 @@ const AdvancedTextEditor = ({
errorClass={errorClass} errorClass={errorClass}
serverError={serverError} serverError={serverError}
channelId={channelId} channelId={channelId}
postId={postId} rootId={rootId}
noArgumentHandleSubmit={handleSubmitWrapper} noArgumentHandleSubmit={handleSubmitWrapper}
isInEditMode={isInEditMode} isInEditMode={isInEditMode}
/> />

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

@@ -17,7 +17,7 @@ interface Props {
errorClass: string | null; errorClass: string | null;
serverError: ServerError & {submittedMessage?: string} | null; serverError: ServerError & {submittedMessage?: string} | null;
channelId: Channel['id']; channelId: Channel['id'];
postId: Post['id']; rootId: Post['id'];
noArgumentHandleSubmit: () => void; noArgumentHandleSubmit: () => void;
isInEditMode: boolean; isInEditMode: boolean;
} }
@@ -27,7 +27,7 @@ export default function Footer({
errorClass, errorClass,
serverError, serverError,
channelId, channelId,
postId, rootId,
noArgumentHandleSubmit, noArgumentHandleSubmit,
isInEditMode, isInEditMode,
}: Props) { }: Props) {
@@ -52,7 +52,7 @@ export default function Footer({
{!isInEditMode && ( {!isInEditMode && (
<MsgTyping <MsgTyping
channelId={channelId} channelId={channelId}
postId={postId} rootId={rootId}
/> />
)} )}
</div> </div>

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

@@ -12,6 +12,7 @@ import {FileTypes} from 'mattermost-redux/action_types';
import {getChannelTimezones} from 'mattermost-redux/actions/channels'; import {getChannelTimezones} from 'mattermost-redux/actions/channels';
import {Permissions} from 'mattermost-redux/constants'; import {Permissions} from 'mattermost-redux/constants';
import {getChannel, getAllChannelStats} from 'mattermost-redux/selectors/entities/channels'; import {getChannel, getAllChannelStats} from 'mattermost-redux/selectors/entities/channels';
import {getFilesIdsForPost} from 'mattermost-redux/selectors/entities/files';
import {getConfig} from 'mattermost-redux/selectors/entities/general'; import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {getPost} from 'mattermost-redux/selectors/entities/posts'; import {getPost} from 'mattermost-redux/selectors/entities/posts';
import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles'; import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles';
@@ -57,7 +58,7 @@ const useSubmit = (
draft: PostDraft, draft: PostDraft,
postError: React.ReactNode, postError: React.ReactNode,
channelId: string, channelId: string,
postId: string, rootId: string,
serverError: (ServerError & { submittedMessage?: string }) | null, serverError: (ServerError & { submittedMessage?: string }) | null,
lastBlurAt: React.MutableRefObject<number>, lastBlurAt: React.MutableRefObject<number>,
focusTextbox: (forceFocust?: boolean) => void, focusTextbox: (forceFocust?: boolean) => void,
@@ -69,6 +70,7 @@ const useSubmit = (
afterSubmit?: (response: SubmitPostReturnType) => void, afterSubmit?: (response: SubmitPostReturnType) => void,
skipCommands?: boolean, skipCommands?: boolean,
isInEditMode?: boolean, isInEditMode?: boolean,
postId?: string,
): [ ): [
(submittingDraft?: PostDraft, schedulingInfo?: SchedulingInfo, options?: CreatePostOptions) => void, (submittingDraft?: PostDraft, schedulingInfo?: SchedulingInfo, options?: CreatePostOptions) => void,
string | null, string | null,
@@ -77,6 +79,8 @@ const useSubmit = (
const dispatch = useDispatch(); const dispatch = useDispatch();
const postFileIds = useSelector((state: GlobalState) => getFilesIdsForPost(state, postId || ''));
const isDraftSubmitting = useRef(false); const isDraftSubmitting = useRef(false);
const [errorClass, setErrorClass] = useState<string | null>(null); const [errorClass, setErrorClass] = useState<string | null>(null);
const isDirectOrGroup = useSelector((state: GlobalState) => { const isDirectOrGroup = useSelector((state: GlobalState) => {
@@ -92,10 +96,10 @@ const useSubmit = (
}); });
const isRootDeleted = useSelector((state: GlobalState) => { const isRootDeleted = useSelector((state: GlobalState) => {
if (!postId) { if (!rootId) {
return false; return false;
} }
const post = getPost(state, postId); const post = getPost(state, rootId);
if (!post || post.delete_at || post.state === 'DELETED') { if (!post || post.delete_at || post.state === 'DELETED') {
return true; return true;
} }
@@ -191,7 +195,7 @@ const useSubmit = (
createAt: 0, createAt: 0,
updateAt: 0, updateAt: 0,
channelId, channelId,
rootId: postId, rootId,
}, {instant: true}); }, {instant: true});
} catch (err: unknown) { } catch (err: unknown) {
if (isServerError(err)) { if (isServerError(err)) {
@@ -209,7 +213,7 @@ const useSubmit = (
return; return;
} }
if (!postId && !schedulingInfo) { if (!rootId && !schedulingInfo) {
dispatch(scrollPostListToBottom()); dispatch(scrollPostListToBottom());
} }
@@ -230,7 +234,7 @@ const useSubmit = (
skipCommands, skipCommands,
afterSubmit, afterSubmit,
afterOptimisticSubmit, afterOptimisticSubmit,
postId, rootId,
showPostDeletedModal, showPostDeletedModal,
handleDraftChange, handleDraftChange,
channelId, channelId,
@@ -238,12 +242,24 @@ const useSubmit = (
]); ]);
const handleFileChange = useCallback((submittingDraft: PostDraft) => { const handleFileChange = useCallback((submittingDraft: PostDraft) => {
// sets the updated data for file IDs by post ID part
dispatch({ dispatch({
type: FileTypes.RECEIVED_FILES_FOR_POST, type: FileTypes.RECEIVED_FILES_FOR_POST,
data: submittingDraft.fileInfos, data: submittingDraft.fileInfos,
postId, postId,
}); });
}, [dispatch, postId]);
// removes the data for the deleted files from store
const deletedFileIds = postFileIds.filter((id: string) => !submittingDraft.fileInfos.find((file) => file.id === id));
if (deletedFileIds) {
dispatch({
type: FileTypes.REMOVED_FILE,
data: {
fileIds: deletedFileIds,
},
});
}
}, [dispatch, postFileIds, postId]);
const setUpdatedFileIds = useCallback((draft: PostDraft) => { const setUpdatedFileIds = useCallback((draft: PostDraft) => {
// new object creation is needed here to support sending a draft with files. // new object creation is needed here to support sending a draft with files.

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

@@ -24,7 +24,6 @@ export default function EditPost() {
const channelId = editingPostDetailsAndPost.post.channel_id; const channelId = editingPostDetailsAndPost.post.channel_id;
const location = editingPostDetailsAndPost.isRHS ? Locations.RHS_COMMENT : Locations.CENTER; const location = editingPostDetailsAndPost.isRHS ? Locations.RHS_COMMENT : Locations.CENTER;
const rootId = editingPostDetailsAndPost.post.root_id || editingPostDetailsAndPost.post.id || '';
const storageKey = `${StoragePrefixes.EDIT_DRAFT}${editingPostDetailsAndPost.post.id}`; const storageKey = `${StoragePrefixes.EDIT_DRAFT}${editingPostDetailsAndPost.post.id}`;
return ( return (
@@ -32,7 +31,8 @@ export default function EditPost() {
<AdvancedTextEditor <AdvancedTextEditor
location={location} location={location}
channelId={channelId} channelId={channelId}
postId={rootId} rootId={editingPostDetailsAndPost.post.root_id}
postId={editingPostDetailsAndPost.post.id}
isInEditMode={true} isInEditMode={true}
storageKey={storageKey} storageKey={storageKey}
placeholder={formatMessage({id: 'edit_post.editPost', defaultMessage: 'Edit the post...'})} placeholder={formatMessage({id: 'edit_post.editPost', defaultMessage: 'Edit the post...'})}

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

@@ -12,14 +12,14 @@ import MsgTyping from './msg_typing';
type OwnProps = { type OwnProps = {
channelId: string; channelId: string;
postId: string; rootId: string;
}; };
function makeMapStateToProps() { function makeMapStateToProps() {
const getUsersTypingByChannelAndPost = makeGetUsersTypingByChannelAndPost(); const getUsersTypingByChannelAndPost = makeGetUsersTypingByChannelAndPost();
return function mapStateToProps(state: GlobalState, ownProps: OwnProps) { return function mapStateToProps(state: GlobalState, ownProps: OwnProps) {
const typingUsers = getUsersTypingByChannelAndPost(state, {channelId: ownProps.channelId, postId: ownProps.postId}); const typingUsers = getUsersTypingByChannelAndPost(state, {channelId: ownProps.channelId, postId: ownProps.rootId});
return { return {
typingUsers, typingUsers,

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

@@ -10,7 +10,7 @@ describe('components/MsgTyping', () => {
const baseProps = { const baseProps = {
typingUsers: [], typingUsers: [],
channelId: 'test', channelId: 'test',
postId: '', rootId: '',
userStartedTyping: jest.fn(), userStartedTyping: jest.fn(),
userStoppedTyping: jest.fn(), userStoppedTyping: jest.fn(),
}; };

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

@@ -11,7 +11,7 @@ import {useWebSocket} from 'utils/use_websocket';
type Props = { type Props = {
channelId: string; channelId: string;
postId: string; rootId: string;
typingUsers: string[]; typingUsers: string[];
userStartedTyping: (userId: string, channelId: string, rootId: string, now: number) => void; userStartedTyping: (userId: string, channelId: string, rootId: string, now: number) => void;
userStoppedTyping: (userId: string, channelId: string, rootId: string, now: number) => void; userStoppedTyping: (userId: string, channelId: string, rootId: string, now: number) => void;
@@ -26,7 +26,7 @@ export default function MsgTyping(props: Props) {
const rootId = msg.data.parent_id; const rootId = msg.data.parent_id;
const userId = msg.data.user_id; const userId = msg.data.user_id;
if (props.channelId === channelId && props.postId === rootId) { if (props.channelId === channelId && props.rootId === rootId) {
userStartedTyping(userId, channelId, rootId, Date.now()); userStartedTyping(userId, channelId, rootId, Date.now());
} }
} else if (msg.event === SocketEvents.POSTED) { } else if (msg.event === SocketEvents.POSTED) {
@@ -36,11 +36,11 @@ export default function MsgTyping(props: Props) {
const rootId = post.root_id; const rootId = post.root_id;
const userId = post.user_id; const userId = post.user_id;
if (props.channelId === channelId && props.postId === rootId) { if (props.channelId === channelId && props.rootId === rootId) {
userStoppedTyping(userId, channelId, rootId, Date.now()); userStoppedTyping(userId, channelId, rootId, Date.now());
} }
} }
}, [props.channelId, props.postId, userStartedTyping, userStoppedTyping]), }, [props.channelId, props.rootId, userStartedTyping, userStoppedTyping]),
}); });
const getTypingText = () => { const getTypingText = () => {