From 685ff406cbfbda8e28d7d3f95806c82c0d15242e Mon Sep 17 00:00:00 2001 From: "Julia Roldi (from Dev Box)" Date: Tue, 28 Jan 2025 18:03:02 -0300 Subject: [PATCH] use content change --- .../lib/imageEdit/ImageEditPlugin.ts | 37 +++++++++---- .../test/imageEdit/ImageEditPluginTest.ts | 54 +++++++++++-------- 2 files changed, 60 insertions(+), 31 deletions(-) diff --git a/packages/roosterjs-content-model-plugins/lib/imageEdit/ImageEditPlugin.ts b/packages/roosterjs-content-model-plugins/lib/imageEdit/ImageEditPlugin.ts index d4c723df34a..f60b99828ad 100644 --- a/packages/roosterjs-content-model-plugins/lib/imageEdit/ImageEditPlugin.ts +++ b/packages/roosterjs-content-model-plugins/lib/imageEdit/ImageEditPlugin.ts @@ -29,6 +29,7 @@ import type { DragAndDropContext } from './types/DragAndDropContext'; import type { ImageHtmlOptions } from './types/ImageHtmlOptions'; import type { ImageEditOptions } from './types/ImageEditOptions'; import type { + ContentChangedEvent, ContentModelImage, EditorPlugin, IEditor, @@ -55,7 +56,7 @@ const MouseRightButton = 2; const DRAG_ID = '_dragging'; const IMAGE_EDIT_CLASS = 'imageEdit'; const IMAGE_EDIT_CLASS_CARET = 'imageEditCaretColor'; -const IMAGE_EDIT_DATASET = 'data-is-editing="true"'; +const IMAGE_EDIT_FORMAT_EVENT = 'ImageEditEvent'; /** * ImageEdit plugin handles the following image editing features: @@ -171,16 +172,11 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin { this.keyDownHandler(this.editor, event); break; case 'contentChanged': - if (event.source == ChangeSource.Drop) { - this.onDropHandler(this.editor); - } + this.contentChangedHandler(this.editor, event); break; case 'extractContentWithDom': this.removeImageEditing(event.clonedRoot); break; - case 'beforeSetContent': - this.beforeSetContentHandler(this.editor, event.newContent); - break; } } @@ -283,9 +279,29 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin { } } - private beforeSetContentHandler(editor: IEditor, newContent: string) { - newContent.replace(IMAGE_EDIT_DATASET, ''); - editor?.setEditorStyle(IMAGE_EDIT_CLASS_CARET, null); + private setContentHandler(editor: IEditor) { + const selection = editor.getDOMSelection(); + if (selection?.type == 'image' && selection.image.dataset.isEditing && !this.isEditing) { + delete selection.image.dataset.isEditing; + } + } + + private contentChangedHandler(editor: IEditor, event: ContentChangedEvent) { + switch (event.source) { + case ChangeSource.SetContent: + this.setContentHandler(editor); + break; + case ChangeSource.Format: + if (this.isEditing && event.formatApiName !== IMAGE_EDIT_FORMAT_EVENT) { + this.cleanInfo(); + this.isEditing = false; + this.isCropMode = false; + } + break; + case ChangeSource.Drop: + this.onDropHandler(editor); + break; + } } /** @@ -401,6 +417,7 @@ export class ImageEditPlugin implements ImageEditor, EditorPlugin { } } }, + apiName: IMAGE_EDIT_FORMAT_EVENT, }, { tryGetFromCache: true, diff --git a/packages/roosterjs-content-model-plugins/test/imageEdit/ImageEditPluginTest.ts b/packages/roosterjs-content-model-plugins/test/imageEdit/ImageEditPluginTest.ts index 22e47507008..53a51cd097c 100644 --- a/packages/roosterjs-content-model-plugins/test/imageEdit/ImageEditPluginTest.ts +++ b/packages/roosterjs-content-model-plugins/test/imageEdit/ImageEditPluginTest.ts @@ -10,9 +10,11 @@ import { ContentModelDocument, ContentModelFormatter, DOMEventRecord, + DOMSelection, EditorEnvironment, FormatContentModelOptions, IEditor, + ImageSelection, } from 'roosterjs-content-model-types'; describe('ImageEditPlugin', () => { @@ -671,44 +673,54 @@ describe('ImageEditPlugin', () => { plugin.dispose(); }); - it('beforeSetContent - should remove isEditing', () => { + it('contentChanged - should remove isEditing', () => { const plugin = new ImageEditPlugin(); + const editor = initEditor('image_edit', [plugin], model); plugin.initialize(editor); - const clonedRoot = document.createElement('div'); const image = document.createElement('img'); - clonedRoot.appendChild(image); - image.dataset['editingInfo'] = JSON.stringify({ - src: 'test', - }); image.dataset['isEditing'] = 'true'; + const selection = { + type: 'image', + image, + } as DOMSelection; + spyOn(editor, 'getDOMSelection').and.returnValue(selection); const event = { - eventType: 'beforeSetContent', - newContent: JSON.stringify(clonedRoot), + eventType: 'contentChanged', + source: ChangeSource.SetContent, } as any; plugin.onPluginEvent(event); - const isEditing = event.newContent.includes('data-is-editing="true"'); - expect(isEditing).toBeFalse(); + const newSelection = editor.getDOMSelection() as ImageSelection; + expect(newSelection!.type).toBe('image'); + expect(newSelection!.image.dataset.isEditing).toBeUndefined(); plugin.dispose(); }); - it('beforeSetContent - should editor caret style', () => { - const plugin = new ImageEditPlugin(); + it('contentChanged - should remove editor caret style', () => { + const plugin = new TestPlugin(); plugin.initialize(editor); - const clonedRoot = document.createElement('div'); - const image = document.createElement('img'); - clonedRoot.appendChild(image); - image.dataset['editingInfo'] = JSON.stringify({ - src: 'test', - }); - image.dataset['isEditing'] = 'true'; + plugin.setIsEditing(true); const event = { - eventType: 'beforeSetContent', - newContent: JSON.stringify(clonedRoot), + eventType: 'contentChanged', + source: ChangeSource.Format, } as any; plugin.onPluginEvent(event); expect(editor.setEditorStyle).toHaveBeenCalledWith('imageEditCaretColor', null); plugin.dispose(); }); + + it('contentChanged - should not remove editor caret style', () => { + const plugin = new TestPlugin(); + plugin.initialize(editor); + plugin.setIsEditing(true); + const event = { + eventType: 'contentChanged', + source: ChangeSource.Format, + formatApiName: 'ImageEditEvent', + } as any; + plugin.onPluginEvent(event); + expect(editor.setEditorStyle).not.toHaveBeenCalled(); + plugin.dispose(); + }); }); class TestPlugin extends ImageEditPlugin {