From a665b6243487c73a7b5f2453112fea6d52e47321 Mon Sep 17 00:00:00 2001 From: Harshil Sharma <18575143+harshilsharma63@users.noreply.github.com> Date: Thu, 16 Jan 2025 07:24:31 +0530 Subject: [PATCH] Deleted file from post ID to file ID and file info part of store (#29871) --- .../advanced_text_editor.tsx | 29 ++++++++++++++++++- .../advanced_text_editor/use_submit.tsx | 12 +++++++- .../src/action_types/files.ts | 2 ++ .../src/reducers/entities/files.ts | 12 ++++++++ .../src/selectors/entities/files.ts | 2 +- 5 files changed, 54 insertions(+), 3 deletions(-) diff --git a/webapp/channels/src/components/advanced_text_editor/advanced_text_editor.tsx b/webapp/channels/src/components/advanced_text_editor/advanced_text_editor.tsx index 8653415905..4e153c2d90 100644 --- a/webapp/channels/src/components/advanced_text_editor/advanced_text_editor.tsx +++ b/webapp/channels/src/components/advanced_text_editor/advanced_text_editor.tsx @@ -9,9 +9,11 @@ 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'; @@ -185,6 +187,7 @@ const AdvancedTextEditor = ({ return enableTutorial && (tutorialStep === tourStep); }); + const postFileIds = useSelector((state: GlobalState) => getFilesIdsForPost(state, postId)); const editorActionsRef = useRef(null); const editorBodyRef = useRef(null); @@ -348,6 +351,26 @@ const AdvancedTextEditor = ({ }); }, [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]); + const handleSubmitWrapper = useCallback(() => { const isEmptyPost = isPostDraftEmpty(draft); @@ -365,8 +388,12 @@ const AdvancedTextEditor = ({ return; } + if (isInEditMode) { + handleFileChangesOnSave(draft); + } + handleSubmit(); - }, [dispatch, draft, handleSubmit, isInEditMode, isRHS]); + }, [dispatch, draft, handleFileChangesOnSave, handleSubmit, isInEditMode, isRHS]); const [handleKeyDown, postMsgKeyPress] = useKeyHandler( draft, diff --git a/webapp/channels/src/components/advanced_text_editor/use_submit.tsx b/webapp/channels/src/components/advanced_text_editor/use_submit.tsx index be0b78b4c2..be3a22283a 100644 --- a/webapp/channels/src/components/advanced_text_editor/use_submit.tsx +++ b/webapp/channels/src/components/advanced_text_editor/use_submit.tsx @@ -8,6 +8,7 @@ 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 {getChannelTimezones} from 'mattermost-redux/actions/channels'; import {Permissions} from 'mattermost-redux/constants'; import {getChannel, getAllChannelStats} from 'mattermost-redux/selectors/entities/channels'; @@ -174,6 +175,7 @@ const useSubmit = ( let response; if (isInEditMode) { response = await dispatch(editPost(submittingDraft)); + handleFileChange(submittingDraft); } else { response = await dispatch(onSubmit(submittingDraft, options, schedulingInfo)); } @@ -235,10 +237,18 @@ const useSubmit = ( isInEditMode, ]); + const handleFileChange = useCallback((submittingDraft: PostDraft) => { + dispatch({ + type: FileTypes.RECEIVED_FILES_FOR_POST, + data: submittingDraft.fileInfos, + postId, + }); + }, [dispatch, postId]); + const setUpdatedFileIds = useCallback((draft: PostDraft) => { // new object creation is needed here to support sending a draft with files. // In case of draft, the PostDraft object is fetched from the redux store, which is immutable. - // When user clicks 'Send Now' in drafts list, it will otherwise try to seta field on an immutable object. + // When user clicks 'Send Now' in drafts list, it will otherwise try to set a field on an immutable object. // Hence, creating a new object here. return { ...draft, diff --git a/webapp/channels/src/packages/mattermost-redux/src/action_types/files.ts b/webapp/channels/src/packages/mattermost-redux/src/action_types/files.ts index 30d28f9b91..d977e4b4c0 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/action_types/files.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/action_types/files.ts @@ -13,4 +13,6 @@ export default keyMirror({ RECEIVED_FILES_FOR_POST: null, RECEIVED_UPLOAD_FILES: null, RECEIVED_FILE_PUBLIC_LINK: null, + + REMOVED_FILE: null, }); diff --git a/webapp/channels/src/packages/mattermost-redux/src/reducers/entities/files.ts b/webapp/channels/src/packages/mattermost-redux/src/reducers/entities/files.ts index 6a0c4f413d..b2270cef73 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/reducers/entities/files.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/reducers/entities/files.ts @@ -54,6 +54,18 @@ export function files(state: Record = {}, action: MMReduxActio return state; } + case FileTypes.REMOVED_FILE: { + const nextState = {...state}; + const {fileIds} = action.data; + if (fileIds) { + fileIds.forEach((id: string) => { + Reflect.deleteProperty(nextState, id); + }); + } + + return nextState; + } + case ChannelBookmarkTypes.RECEIVED_BOOKMARKS: { const bookmarks: ChannelBookmark[] = action.data.bookmarks; diff --git a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/files.ts b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/files.ts index d420d08a23..16c55eb397 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/files.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/files.ts @@ -21,7 +21,7 @@ function getAllFilesFromSearch(state: GlobalState) { return state.entities.files.filesFromSearch; } -function getFilesIdsForPost(state: GlobalState, postId: string) { +export function getFilesIdsForPost(state: GlobalState, postId: string) { if (postId) { return state.entities.files.fileIdsByPostId[postId] || []; }