Skip to content

Commit

Permalink
Merge pull request #2792 from microsoft/u/juliaroldi/safari-image-sel…
Browse files Browse the repository at this point in the history
…ection

Do not remove image selection when copy
  • Loading branch information
juliaroldi authored Sep 13, 2024
2 parents 1c20684 + cb81038 commit c872e31
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { addRangeToSelection } from '../../coreApi/setDOMSelection/addRangeToSelection';
import { deleteEmptyList } from './deleteEmptyList';
import { adjustImageSelectionOnSafari } from './utils/adjustImageSelectionOnSafari';
import { deleteEmptyList } from './utils/deleteEmptyList';
import { onCreateCopyEntityNode } from '../../override/pasteCopyBlockEntityParser';
import { paste } from '../../command/paste/paste';

import {
ChangeSource,
contentModelToDom,
Expand Down Expand Up @@ -110,6 +110,8 @@ class CopyPastePlugin implements PluginWithState<CopyPastePluginState> {
const doc = this.editor.getDocument();
const selection = this.editor.getDOMSelection();

adjustImageSelectionOnSafari(this.editor, selection);

if (selection && (selection.type != 'range' || !selection.range.collapsed)) {
const pasteModel = this.editor.getContentModelCopy('disconnected');

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { IEditor, DOMSelection } from 'roosterjs-content-model-types';

/**
* @internal
* Adjust Image selection, so the copy by keyboard does not remove image selection.
*/
export function adjustImageSelectionOnSafari(editor: IEditor, selection: DOMSelection | null) {
if (editor.getEnvironment().isSafari && selection?.type == 'image') {
const range = new Range();
range.setStartBefore(selection.image);
range.setEndAfter(selection.image);
editor.setDOMSelection({
range,
type: 'range',
isReverted: false,
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { adjustImageSelectionOnSafari } from '../../../../lib/corePlugin/copyPaste/utils/adjustImageSelectionOnSafari';
import type { DOMSelection, IEditor } from 'roosterjs-content-model-types';

describe('adjustImageSelectionOnSafari', () => {
let getEnvironmentSpy: jasmine.Spy;
let setDOMSelectionSpy: jasmine.Spy;
let editor: IEditor;

beforeEach(() => {
getEnvironmentSpy = jasmine.createSpy('getEnvironment');
setDOMSelectionSpy = jasmine.createSpy('setDOMSelection');
editor = ({
getEnvironment: getEnvironmentSpy,
setDOMSelection: setDOMSelectionSpy,
} as any) as IEditor;
});

it('should adjustSelection', () => {
getEnvironmentSpy.and.returnValue({
isSafari: true,
});
const image = document.createElement('img');
document.body.appendChild(image);
const selection: DOMSelection = {
type: 'image',
image: image,
};
const range = new Range();
range.setStartBefore(image);
range.setEndAfter(image);

adjustImageSelectionOnSafari(editor, selection);
expect(setDOMSelectionSpy).toHaveBeenCalledTimes(1);
expect(setDOMSelectionSpy).toHaveBeenCalledWith({
range: range,
type: 'range',
isReverted: false,
});

document.body.removeChild(image);
});

it('should not adjustSelection - it is not safari', () => {
getEnvironmentSpy.and.returnValue({
isSafari: false,
});
const image = new Image();
const selection: DOMSelection = {
type: 'image',
image: image,
};

adjustImageSelectionOnSafari(editor, selection);
expect(setDOMSelectionSpy).not.toHaveBeenCalled();
});

it('should not adjustSelection - it is not image', () => {
getEnvironmentSpy.and.returnValue({
isSafari: true,
});
const selection: DOMSelection = {
type: 'range',
range: new Range(),
isReverted: false,
};

adjustImageSelectionOnSafari(editor, selection);
expect(setDOMSelectionSpy).not.toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ContentModelBlockGroup, ContentModelSelectionMarker } from 'roosterjs-content-model-types';
import { deleteEmptyList } from '../../../lib/corePlugin/copyPaste/deleteEmptyList';
import { deleteEmptyList } from '../../../../lib/corePlugin/copyPaste/utils/deleteEmptyList';
import { deleteSelection } from 'roosterjs-content-model-dom/lib/modelApi/editing/deleteSelection';
import {
createContentModelDocument,
Expand Down

0 comments on commit c872e31

Please sign in to comment.