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
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
c1d4f5cb9f
Коммит
c951a9cfac
@@ -302,7 +302,10 @@ describe('Keyboard Shortcuts', () => {
|
||||
cy.uiGetPostTextBox().type('{uparrow}');
|
||||
|
||||
// # 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.getLastPost().within(() => {
|
||||
|
||||
@@ -732,7 +732,7 @@ describe('Messaging', () => {
|
||||
cy.get('#edit_textbox').should('be.visible');
|
||||
|
||||
// * 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
|
||||
cy.get(`#searchResult_${postId}`).findByText('Edited').should('exist');
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import {expect, Locator} from '@playwright/test';
|
||||
import path from 'node:path';
|
||||
import {waitUntil} from '@e2e-support/test_action';
|
||||
|
||||
export default class ChannelsPostCreate {
|
||||
readonly container: Locator;
|
||||
@@ -106,6 +107,12 @@ export default class ChannelsPostCreate {
|
||||
});
|
||||
|
||||
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();
|
||||
|
||||
@@ -39,7 +39,7 @@ const AdvancedCreateComment = ({
|
||||
<AdvancedTextEditor
|
||||
location={Locations.RHS_COMMENT}
|
||||
channelId={channelId}
|
||||
postId={rootId}
|
||||
rootId={rootId}
|
||||
isThreadView={isThreadView}
|
||||
placeholder={placeholder}
|
||||
afterSubmit={afterSubmit}
|
||||
|
||||
@@ -22,7 +22,7 @@ const AdvancedCreatePost = () => {
|
||||
return (
|
||||
<AdvancedTextEditor
|
||||
location={Locations.CENTER}
|
||||
postId={''}
|
||||
rootId={''}
|
||||
channelId={currentChannelId}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -130,7 +130,7 @@ const baseProps = {
|
||||
uploadsProgressPercent: {},
|
||||
currentChannel: initialState.entities.channels.channels.current_channel_id as Channel,
|
||||
channelId,
|
||||
postId: '',
|
||||
rootId: '',
|
||||
errorClass: null,
|
||||
serverError: 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', () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
postId: 'post_id_1',
|
||||
rootId: 'post_id_1',
|
||||
isInEditMode: true,
|
||||
};
|
||||
|
||||
@@ -457,7 +457,7 @@ describe('components/avanced_text_editor/advanced_text_editor', () => {
|
||||
);
|
||||
expect(container.querySelector('#createPostFileDropOverlay')).toBeVisible();
|
||||
|
||||
props.postId = 'post_id_1';
|
||||
props.rootId = 'post_id_1';
|
||||
rerender(<AdvancedTextEditor {...props}/>);
|
||||
expect(container.querySelector('#createCommentFileDropOverlay')).toBeVisible();
|
||||
|
||||
|
||||
@@ -9,11 +9,9 @@ import {useDispatch, useSelector} from 'react-redux';
|
||||
import type {ServerError} from '@mattermost/types/errors';
|
||||
import type {SchedulingInfo} from '@mattermost/types/schedule_post';
|
||||
|
||||
import {FileTypes} from 'mattermost-redux/action_types';
|
||||
import {savePreferences} from 'mattermost-redux/actions/preferences';
|
||||
import {Permissions} from 'mattermost-redux/constants';
|
||||
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 {get, getBool, getInt} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles';
|
||||
@@ -98,7 +96,8 @@ export type Props = {
|
||||
*/
|
||||
location: string;
|
||||
channelId: string;
|
||||
postId: string;
|
||||
rootId: string;
|
||||
postId?: string;
|
||||
isThreadView?: boolean;
|
||||
placeholder?: string;
|
||||
isInEditMode?: boolean;
|
||||
@@ -118,6 +117,7 @@ export type Props = {
|
||||
const AdvancedTextEditor = ({
|
||||
location,
|
||||
channelId,
|
||||
rootId,
|
||||
postId,
|
||||
isThreadView = false,
|
||||
placeholder,
|
||||
@@ -146,7 +146,7 @@ const AdvancedTextEditor = ({
|
||||
textboxId = AdvancedTextEditorTextboxIds.Default;
|
||||
}
|
||||
|
||||
const isRHS = Boolean(postId && !isThreadView);
|
||||
const isRHS = isThreadView ? false : Boolean(rootId) || location === Locations.RHS_COMMENT;
|
||||
|
||||
const getFormattingBarPreferenceName = () => {
|
||||
let name: string;
|
||||
@@ -164,7 +164,7 @@ const AdvancedTextEditor = ({
|
||||
const channelDisplayName = channel?.display_name || '';
|
||||
const channelType = channel?.type || '';
|
||||
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 maxPostSize = useSelector((state: GlobalState) => parseInt(getConfig(state).MaxPostSize || '', 10) || Constants.DEFAULT_CHARACTER_LIMIT);
|
||||
const canUploadFiles = useSelector((state: GlobalState) => canUploadFilesAccordingToConfig(getConfig(state)));
|
||||
@@ -188,7 +188,7 @@ const AdvancedTextEditor = ({
|
||||
});
|
||||
const showSendTutorialTip = useSelector((state: GlobalState) => {
|
||||
// We don't show the tutorial tip neither on RHS nor Thread view
|
||||
if (postId) {
|
||||
if (rootId) {
|
||||
return false;
|
||||
}
|
||||
const config = getConfig(state);
|
||||
@@ -202,7 +202,6 @@ const AdvancedTextEditor = ({
|
||||
|
||||
return enableTutorial && (tutorialStep === tourStep);
|
||||
});
|
||||
const postFileIds = useSelector((state: GlobalState) => getFilesIdsForPost(state, postId));
|
||||
|
||||
const editorActionsRef = useRef<HTMLDivElement>(null);
|
||||
const editorBodyRef = useRef<HTMLDivElement>(null);
|
||||
@@ -235,8 +234,8 @@ const AdvancedTextEditor = ({
|
||||
}, []);
|
||||
|
||||
const emitTypingEvent = useCallback(() => {
|
||||
GlobalActions.emitLocalUserTypingEvent(channelId, postId);
|
||||
}, [channelId, postId]);
|
||||
GlobalActions.emitLocalUserTypingEvent(channelId, rootId);
|
||||
}, [channelId, rootId]);
|
||||
|
||||
const handleDraftChange = useCallback((draftToChange: PostDraft, options: {instant?: boolean; show?: boolean} = {instant: false, show: false}) => {
|
||||
if (saveDraftFrame.current) {
|
||||
@@ -307,12 +306,12 @@ const AdvancedTextEditor = ({
|
||||
}]));
|
||||
}, [dispatch, currentUserId, getFormattingBarPreferenceName, isFormattingBarHidden]);
|
||||
|
||||
useOrientationHandler(textboxRef, postId);
|
||||
useOrientationHandler(textboxRef, rootId);
|
||||
const pluginItems = usePluginItems(draft, textboxRef, handleDraftChange);
|
||||
const focusTextbox = useTextboxFocus(textboxRef, channelId, isRHS, canPost);
|
||||
const [attachmentPreview, fileUploadJSX] = useUploadFiles(
|
||||
draft,
|
||||
postId,
|
||||
rootId,
|
||||
channelId,
|
||||
isThreadView,
|
||||
storedDrafts,
|
||||
@@ -348,7 +347,7 @@ const AdvancedTextEditor = ({
|
||||
draft,
|
||||
postError,
|
||||
channelId,
|
||||
postId,
|
||||
rootId,
|
||||
serverError,
|
||||
lastBlurAt,
|
||||
focusTextbox,
|
||||
@@ -360,6 +359,7 @@ const AdvancedTextEditor = ({
|
||||
afterSubmit,
|
||||
undefined,
|
||||
isInEditMode,
|
||||
postId,
|
||||
);
|
||||
|
||||
const handleSubmitWithErrorHandling = useCallback((submittingDraft?: PostDraft, schedulingInfo?: SchedulingInfo, options?: CreatePostOptions) => {
|
||||
@@ -383,30 +383,10 @@ const AdvancedTextEditor = ({
|
||||
createAt: 0,
|
||||
updateAt: 0,
|
||||
channelId,
|
||||
rootId: postId,
|
||||
rootId,
|
||||
metadata: {},
|
||||
});
|
||||
}, [handleDraftChange, channelId, postId]);
|
||||
|
||||
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]);
|
||||
}, [handleDraftChange, channelId, rootId]);
|
||||
|
||||
const handleSubmitWrapper = useCallback(() => {
|
||||
const isEmptyPost = isPostDraftEmpty(draft);
|
||||
@@ -425,17 +405,13 @@ const AdvancedTextEditor = ({
|
||||
return;
|
||||
}
|
||||
|
||||
if (isInEditMode) {
|
||||
handleFileChangesOnSave(draft);
|
||||
}
|
||||
|
||||
handleSubmitWithErrorHandling();
|
||||
}, [dispatch, draft, handleFileChangesOnSave, handleSubmitWithErrorHandling, isInEditMode, isRHS]);
|
||||
}, [dispatch, draft, handleSubmitWithErrorHandling, isInEditMode, isRHS]);
|
||||
|
||||
const [handleKeyDown, postMsgKeyPress] = useKeyHandler(
|
||||
draft,
|
||||
channelId,
|
||||
postId,
|
||||
rootId,
|
||||
caretPosition,
|
||||
isValidPersistentNotifications,
|
||||
location,
|
||||
@@ -583,11 +559,11 @@ const AdvancedTextEditor = ({
|
||||
useEffect(() => {
|
||||
setShowPreview(false);
|
||||
setServerError(null);
|
||||
}, [channelId, postId]);
|
||||
}, [channelId, rootId]);
|
||||
|
||||
// Remove uploads in progress on mount
|
||||
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) {
|
||||
return draft;
|
||||
}
|
||||
@@ -626,7 +602,7 @@ const AdvancedTextEditor = ({
|
||||
handleDraftChange(draftRef.current, {instant: true, show: true});
|
||||
}
|
||||
};
|
||||
}, [channelId, postId]);
|
||||
}, [channelId, rootId]);
|
||||
|
||||
const disableSendButton = Boolean(isDisabled || (!draft.message.trim().length && !draft.fileInfos.length)) || !isValidPersistentNotifications;
|
||||
const sendButton = readOnlyChannel || isInEditMode ? null : (
|
||||
@@ -647,7 +623,7 @@ const AdvancedTextEditor = ({
|
||||
let createMessage;
|
||||
if (placeholder) {
|
||||
createMessage = placeholder;
|
||||
} else if (!postId && !isDisabled) {
|
||||
} else if (!rootId && !isDisabled) {
|
||||
createMessage = formatMessage(
|
||||
{
|
||||
id: 'create_post.write',
|
||||
@@ -750,9 +726,9 @@ const AdvancedTextEditor = ({
|
||||
|
||||
return (
|
||||
<form
|
||||
id={postId ? undefined : 'create_post'}
|
||||
data-testid={postId ? undefined : 'create-post'}
|
||||
className={(!postId && !fullWidthTextBox) ? 'center' : undefined}
|
||||
id={rootId ? undefined : 'create_post'}
|
||||
data-testid={rootId ? undefined : 'create-post'}
|
||||
className={(!rootId && !fullWidthTextBox) ? 'center' : undefined}
|
||||
onSubmit={handleSubmitWithEvent}
|
||||
>
|
||||
{canPost && (draft.fileInfos.length > 0 || draft.uploadsInProgress.length > 0) && (
|
||||
@@ -764,7 +740,7 @@ const AdvancedTextEditor = ({
|
||||
channelId={channelId}
|
||||
teammateDisplayName={teammateDisplayName}
|
||||
location={location}
|
||||
postId={postId}
|
||||
postId={rootId}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
@@ -824,7 +800,7 @@ const AdvancedTextEditor = ({
|
||||
preview={showPreview}
|
||||
badConnection={badConnection}
|
||||
useChannelMentions={useChannelMentions}
|
||||
rootId={postId}
|
||||
rootId={rootId}
|
||||
onWidthChange={handleWidthChange}
|
||||
isInEditMode={isInEditMode}
|
||||
/>
|
||||
@@ -876,7 +852,7 @@ const AdvancedTextEditor = ({
|
||||
errorClass={errorClass}
|
||||
serverError={serverError}
|
||||
channelId={channelId}
|
||||
postId={postId}
|
||||
rootId={rootId}
|
||||
noArgumentHandleSubmit={handleSubmitWrapper}
|
||||
isInEditMode={isInEditMode}
|
||||
/>
|
||||
|
||||
@@ -17,7 +17,7 @@ interface Props {
|
||||
errorClass: string | null;
|
||||
serverError: ServerError & {submittedMessage?: string} | null;
|
||||
channelId: Channel['id'];
|
||||
postId: Post['id'];
|
||||
rootId: Post['id'];
|
||||
noArgumentHandleSubmit: () => void;
|
||||
isInEditMode: boolean;
|
||||
}
|
||||
@@ -27,7 +27,7 @@ export default function Footer({
|
||||
errorClass,
|
||||
serverError,
|
||||
channelId,
|
||||
postId,
|
||||
rootId,
|
||||
noArgumentHandleSubmit,
|
||||
isInEditMode,
|
||||
}: Props) {
|
||||
@@ -52,7 +52,7 @@ export default function Footer({
|
||||
{!isInEditMode && (
|
||||
<MsgTyping
|
||||
channelId={channelId}
|
||||
postId={postId}
|
||||
rootId={rootId}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,7 @@ import {FileTypes} from 'mattermost-redux/action_types';
|
||||
import {getChannelTimezones} from 'mattermost-redux/actions/channels';
|
||||
import {Permissions} from 'mattermost-redux/constants';
|
||||
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 {getPost} from 'mattermost-redux/selectors/entities/posts';
|
||||
import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles';
|
||||
@@ -57,7 +58,7 @@ const useSubmit = (
|
||||
draft: PostDraft,
|
||||
postError: React.ReactNode,
|
||||
channelId: string,
|
||||
postId: string,
|
||||
rootId: string,
|
||||
serverError: (ServerError & { submittedMessage?: string }) | null,
|
||||
lastBlurAt: React.MutableRefObject<number>,
|
||||
focusTextbox: (forceFocust?: boolean) => void,
|
||||
@@ -69,6 +70,7 @@ const useSubmit = (
|
||||
afterSubmit?: (response: SubmitPostReturnType) => void,
|
||||
skipCommands?: boolean,
|
||||
isInEditMode?: boolean,
|
||||
postId?: string,
|
||||
): [
|
||||
(submittingDraft?: PostDraft, schedulingInfo?: SchedulingInfo, options?: CreatePostOptions) => void,
|
||||
string | null,
|
||||
@@ -77,6 +79,8 @@ const useSubmit = (
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const postFileIds = useSelector((state: GlobalState) => getFilesIdsForPost(state, postId || ''));
|
||||
|
||||
const isDraftSubmitting = useRef(false);
|
||||
const [errorClass, setErrorClass] = useState<string | null>(null);
|
||||
const isDirectOrGroup = useSelector((state: GlobalState) => {
|
||||
@@ -92,10 +96,10 @@ const useSubmit = (
|
||||
});
|
||||
|
||||
const isRootDeleted = useSelector((state: GlobalState) => {
|
||||
if (!postId) {
|
||||
if (!rootId) {
|
||||
return false;
|
||||
}
|
||||
const post = getPost(state, postId);
|
||||
const post = getPost(state, rootId);
|
||||
if (!post || post.delete_at || post.state === 'DELETED') {
|
||||
return true;
|
||||
}
|
||||
@@ -191,7 +195,7 @@ const useSubmit = (
|
||||
createAt: 0,
|
||||
updateAt: 0,
|
||||
channelId,
|
||||
rootId: postId,
|
||||
rootId,
|
||||
}, {instant: true});
|
||||
} catch (err: unknown) {
|
||||
if (isServerError(err)) {
|
||||
@@ -209,7 +213,7 @@ const useSubmit = (
|
||||
return;
|
||||
}
|
||||
|
||||
if (!postId && !schedulingInfo) {
|
||||
if (!rootId && !schedulingInfo) {
|
||||
dispatch(scrollPostListToBottom());
|
||||
}
|
||||
|
||||
@@ -230,7 +234,7 @@ const useSubmit = (
|
||||
skipCommands,
|
||||
afterSubmit,
|
||||
afterOptimisticSubmit,
|
||||
postId,
|
||||
rootId,
|
||||
showPostDeletedModal,
|
||||
handleDraftChange,
|
||||
channelId,
|
||||
@@ -238,12 +242,24 @@ const useSubmit = (
|
||||
]);
|
||||
|
||||
const handleFileChange = useCallback((submittingDraft: PostDraft) => {
|
||||
// sets the updated data for file IDs by post ID part
|
||||
dispatch({
|
||||
type: FileTypes.RECEIVED_FILES_FOR_POST,
|
||||
data: submittingDraft.fileInfos,
|
||||
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) => {
|
||||
// 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 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}`;
|
||||
|
||||
return (
|
||||
@@ -32,7 +31,8 @@ export default function EditPost() {
|
||||
<AdvancedTextEditor
|
||||
location={location}
|
||||
channelId={channelId}
|
||||
postId={rootId}
|
||||
rootId={editingPostDetailsAndPost.post.root_id}
|
||||
postId={editingPostDetailsAndPost.post.id}
|
||||
isInEditMode={true}
|
||||
storageKey={storageKey}
|
||||
placeholder={formatMessage({id: 'edit_post.editPost', defaultMessage: 'Edit the post...'})}
|
||||
|
||||
@@ -12,14 +12,14 @@ import MsgTyping from './msg_typing';
|
||||
|
||||
type OwnProps = {
|
||||
channelId: string;
|
||||
postId: string;
|
||||
rootId: string;
|
||||
};
|
||||
|
||||
function makeMapStateToProps() {
|
||||
const getUsersTypingByChannelAndPost = makeGetUsersTypingByChannelAndPost();
|
||||
|
||||
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 {
|
||||
typingUsers,
|
||||
|
||||
@@ -10,7 +10,7 @@ describe('components/MsgTyping', () => {
|
||||
const baseProps = {
|
||||
typingUsers: [],
|
||||
channelId: 'test',
|
||||
postId: '',
|
||||
rootId: '',
|
||||
userStartedTyping: jest.fn(),
|
||||
userStoppedTyping: jest.fn(),
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ import {useWebSocket} from 'utils/use_websocket';
|
||||
|
||||
type Props = {
|
||||
channelId: string;
|
||||
postId: string;
|
||||
rootId: string;
|
||||
typingUsers: string[];
|
||||
userStartedTyping: (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 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());
|
||||
}
|
||||
} else if (msg.event === SocketEvents.POSTED) {
|
||||
@@ -36,11 +36,11 @@ export default function MsgTyping(props: Props) {
|
||||
const rootId = post.root_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());
|
||||
}
|
||||
}
|
||||
}, [props.channelId, props.postId, userStartedTyping, userStoppedTyping]),
|
||||
}, [props.channelId, props.rootId, userStartedTyping, userStoppedTyping]),
|
||||
});
|
||||
|
||||
const getTypingText = () => {
|
||||
|
||||
Ссылка в новой задаче
Block a user