@@ -18,33 +18,27 @@ import { ActivityRichTextEditorChangeOnActivityIdEffect } from '@/activities/com
1818import { type Attachment } from '@/activities/files/types/Attachment' ;
1919import { type Note } from '@/activities/types/Note' ;
2020import { type Task } from '@/activities/types/Task' ;
21- import { filterAttachmentsToRestore } from '@/activities/utils/filterAttachmentsToRestore' ;
22- import { getActivityAttachmentIdsAndNameToUpdate } from '@/activities/utils/getActivityAttachmentIdsAndNameToUpdate' ;
23- import { getActivityAttachmentIdsToDelete } from '@/activities/utils/getActivityAttachmentIdsToDelete' ;
24- import { getActivityAttachmentPathsToRestore } from '@/activities/utils/getActivityAttachmentPathsToRestore' ;
2521import { SIDE_PANEL_FOCUS_ID } from '@/command-menu/constants/SidePanelFocusId' ;
2622import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient' ;
2723import { useLabelIdentifierFieldMetadataItem } from '@/object-metadata/hooks/useLabelIdentifierFieldMetadataItem' ;
28- import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords' ;
2924import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords' ;
30- import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRecords' ;
31- import { useRestoreManyRecords } from '@/object-record/hooks/useRestoreManyRecords' ;
32- import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord' ;
3325import { useIsRecordFieldReadOnly } from '@/object-record/read-only/hooks/useIsRecordFieldReadOnly' ;
3426import { isTitleCellInEditModeComponentState } from '@/object-record/record-title-cell/states/isTitleCellInEditModeComponentState' ;
3527import { RecordTitleCellContainerType } from '@/object-record/record-title-cell/types/RecordTitleCellContainerType' ;
3628import { getRecordFieldInputInstanceId } from '@/object-record/utils/getRecordFieldInputId' ;
3729import { BlockEditor } from '@/ui/input/editor/components/BlockEditor' ;
30+ import { BLOCK_EDITOR_GLOBAL_HOTKEYS_CONFIG } from '@/ui/input/editor/constants/BlockEditorGlobalHotkeysConfig' ;
31+ import { useAttachmentSync } from '@/ui/input/editor/hooks/useAttachmentSync' ;
32+ import { parseInitialBlocknote } from '@/ui/input/editor/utils/parseInitialBlocknote' ;
33+ import { prepareBodyWithSignedUrls } from '@/ui/input/editor/utils/prepareBodyWithSignedUrls' ;
3834import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack' ;
3935import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById' ;
4036import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType' ;
4137import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement' ;
42- import type { PartialBlock } from '@blocknote/core' ;
4338import '@blocknote/core/fonts/inter.css' ;
4439import '@blocknote/mantine/style.css' ;
4540import { useCreateBlockNote } from '@blocknote/react' ;
4641import '@blocknote/react/style.css' ;
47- import { isArray , isNonEmptyString } from '@sniptt/guards' ;
4842import { isDefined } from 'twenty-shared/utils' ;
4943
5044type ActivityRichTextEditorProps = {
@@ -72,14 +66,6 @@ export const ActivityRichTextEditor = ({
7266 ( field ) => field . name === 'bodyV2' ,
7367 ) ;
7468
75- const { deleteManyRecords : deleteAttachments } = useDeleteManyRecords ( {
76- objectNameSingular : CoreObjectNameSingular . Attachment ,
77- } ) ;
78-
79- const { restoreManyRecords : restoreAttachments } = useRestoreManyRecords ( {
80- objectNameSingular : CoreObjectNameSingular . Attachment ,
81- } ) ;
82-
8369 const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack ( ) ;
8470 const { removeFocusItemFromFocusStackById } =
8571 useRemoveFocusItemFromFocusStackById ( ) ;
@@ -102,18 +88,8 @@ export const ActivityRichTextEditor = ({
10288 } ,
10389 } ) ;
10490
105- const { fetchAllRecords : findSoftDeletedAttachments } =
106- useLazyFetchAllRecords ( {
107- objectNameSingular : CoreObjectNameSingular . Attachment ,
108- filter : {
109- deletedAt : {
110- is : 'NOT_NULL' ,
111- } ,
112- } ,
113- } ) ;
114- const { updateOneRecord : updateOneAttachment } = useUpdateOneRecord ( {
115- objectNameSingular : CoreObjectNameSingular . Attachment ,
116- } ) ;
91+ const { syncAttachments } = useAttachmentSync ( attachments ) ;
92+
11793 const { upsertActivity } = useUpsertActivity ( {
11894 activityObjectNameSingular : activityObjectNameSingular ,
11995 } ) ;
@@ -155,37 +131,13 @@ export const ActivityRichTextEditor = ({
155131 } ) ;
156132 } ;
157133
158- const prepareBody = ( newStringifiedBody : string ) => {
159- if ( ! newStringifiedBody ) return newStringifiedBody ;
160-
161- const body = JSON . parse ( newStringifiedBody ) ;
162-
163- const bodyWithSignedPayload = body . map ( ( block : any ) => {
164- if ( block . type !== 'image' || ! block . props . url ) {
165- return block ;
166- }
167-
168- const imageProps = block . props ;
169- const imageUrl = new URL ( imageProps . url ) ;
170-
171- return {
172- ...block ,
173- props : {
174- ...imageProps ,
175- url : `${ imageUrl . toString ( ) } ` ,
176- } ,
177- } ;
178- } ) ;
179- return JSON . stringify ( bodyWithSignedPayload ) ;
180- } ;
181-
182134 const handlePersistBody = useCallback (
183135 ( activityBody : string ) => {
184136 if ( ! canCreateActivity ) {
185137 setCanCreateActivity ( true ) ;
186138 }
187139
188- persistBodyDebounced ( prepareBody ( activityBody ) ) ;
140+ persistBodyDebounced ( prepareBodyWithSignedUrls ( activityBody ) ) ;
189141 } ,
190142 [ persistBodyDebounced , setCanCreateActivity , canCreateActivity ] ,
191143 ) ;
@@ -225,60 +177,17 @@ export const ActivityRichTextEditor = ({
225177
226178 handlePersistBody ( newStringifiedBody ) ;
227179
228- const attachmentIdsToDelete = getActivityAttachmentIdsToDelete (
180+ await syncAttachments (
229181 newStringifiedBody ,
230- attachments ,
231182 oldActivity ?. bodyV2 . blocknote ,
232183 ) ;
233-
234- if ( attachmentIdsToDelete . length > 0 ) {
235- await deleteAttachments ( {
236- recordIdsToDelete : attachmentIdsToDelete ,
237- } ) ;
238- }
239-
240- const attachmentPathsToRestore = getActivityAttachmentPathsToRestore (
241- newStringifiedBody ,
242- attachments ,
243- ) ;
244-
245- if ( attachmentPathsToRestore . length > 0 ) {
246- const softDeletedAttachments =
247- ( await findSoftDeletedAttachments ( ) ) as Attachment [ ] ;
248-
249- const attachmentIdsToRestore = filterAttachmentsToRestore (
250- attachmentPathsToRestore ,
251- softDeletedAttachments ,
252- ) ;
253-
254- await restoreAttachments ( {
255- idsToRestore : attachmentIdsToRestore ,
256- } ) ;
257- }
258- const attachmentsToUpdate = getActivityAttachmentIdsAndNameToUpdate (
259- newStringifiedBody ,
260- attachments ,
261- ) ;
262- if ( attachmentsToUpdate . length > 0 ) {
263- for ( const attachmentToUpdate of attachmentsToUpdate ) {
264- if ( ! attachmentToUpdate . id ) continue ;
265- await updateOneAttachment ( {
266- idToUpdate : attachmentToUpdate . id ,
267- updateOneRecordInput : { name : attachmentToUpdate . name } ,
268- } ) ;
269- }
270- }
271184 } ,
272185 [
273- attachments ,
274186 activityId ,
275187 cache ,
276188 objectMetadataItemActivity ,
277189 handlePersistBody ,
278- deleteAttachments ,
279- restoreAttachments ,
280- findSoftDeletedAttachments ,
281- updateOneAttachment ,
190+ syncAttachments ,
282191 ] ,
283192 ) ;
284193
@@ -291,35 +200,14 @@ export const ActivityRichTextEditor = ({
291200 } ;
292201
293202 const initialBody = useMemo ( ( ) => {
294- const blocknote = activity ?. bodyV2 ?. blocknote ;
295-
296- if (
297- isDefined ( activity ) &&
298- isNonEmptyString ( blocknote ) &&
299- blocknote !== '{}'
300- ) {
301- let parsedBody : PartialBlock [ ] | undefined = undefined ;
302-
303- // TODO: Remove this once we have removed the old rich text
304- try {
305- parsedBody = JSON . parse ( blocknote ) ;
306- } catch {
307- // eslint-disable-next-line no-console
308- console . warn (
309- `Failed to parse body for activity ${ activityId } , for rich text version 'v2'` ,
310- ) ;
311- // eslint-disable-next-line no-console
312- console . warn ( blocknote ) ;
313- }
314-
315- if ( isArray ( parsedBody ) && parsedBody . length === 0 ) {
316- return undefined ;
317- }
318-
319- return parsedBody ;
203+ if ( ! isDefined ( activity ) ) {
204+ return undefined ;
320205 }
321206
322- return undefined ;
207+ return parseInitialBlocknote (
208+ activity ?. bodyV2 ?. blocknote ,
209+ `Failed to parse body for activity ${ activityId } , for rich text version 'v2'` ,
210+ ) ;
323211 } , [ activity , activityId ] ) ;
324212
325213 const handleEditorBuiltInUploadFile = async ( file : File ) => {
@@ -431,10 +319,7 @@ export const ActivityRichTextEditor = ({
431319 type : FocusComponentType . ACTIVITY_RICH_TEXT_EDITOR ,
432320 } ,
433321 focusId : activityId ,
434- globalHotkeysConfig : {
435- enableGlobalHotkeysConflictingWithKeyboard : false ,
436- enableGlobalHotkeysWithModifiers : true ,
437- } ,
322+ globalHotkeysConfig : BLOCK_EDITOR_GLOBAL_HOTKEYS_CONFIG ,
438323 } ) ;
439324 } ,
440325 [ recordTitleCellId , activityId , editor , pushFocusItemToFocusStack ] ,
0 commit comments