Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port Image Edit Operations #2670

Merged
merged 62 commits into from
Jun 5, 2024
Merged
Changes from 1 commit
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
52f30e4
WIP
juliaroldi Apr 5, 2024
5bb6b15
fix conflicts
juliaroldi Apr 5, 2024
36f592c
conflict
juliaroldi Apr 5, 2024
ec80d60
WIP
juliaroldi Apr 5, 2024
4aa4828
Merge branch 'master' of https://github.com/microsoft/roosterjs into …
juliaroldi Apr 5, 2024
ec97315
WIP
juliaroldi Apr 5, 2024
531985b
WIP
juliaroldi Apr 8, 2024
b91e403
croppers
juliaroldi Apr 10, 2024
7a06999
porting
juliaroldi Apr 11, 2024
091f2db
WIPP
juliaroldi Apr 12, 2024
c11771f
fix conflicts
juliaroldi Apr 17, 2024
13dcca1
WIP
juliaroldi Apr 18, 2024
816b769
Merge branch 'master' of https://github.com/microsoft/roosterjs into …
juliaroldi Apr 22, 2024
cc260bc
WIP
juliaroldi Apr 23, 2024
b7a0ca8
conflicts
juliaroldi Apr 23, 2024
a1586a5
fixes
juliaroldi Apr 23, 2024
89d51b1
WIP
juliaroldi Apr 24, 2024
63125da
Merge branch 'master' of https://github.com/microsoft/roosterjs into …
juliaroldi Apr 24, 2024
21599f9
fix build
juliaroldi Apr 25, 2024
cca526e
remove function
juliaroldi Apr 25, 2024
7b5cd18
wip: clean/refactor
juliaroldi Apr 26, 2024
75bea9e
wip: clean
juliaroldi Apr 26, 2024
554e3da
clean
juliaroldi Apr 26, 2024
207657d
wip
juliaroldi Apr 26, 2024
3806813
Merge branch 'u/juliaroldi/image-span' of https://github.com/microsof…
juliaroldi Apr 29, 2024
3221722
WIP
juliaroldi Apr 29, 2024
8a50224
Merge branch 'u/juliaroldi/image-span' of https://github.com/microsof…
juliaroldi Apr 30, 2024
abe2b18
wip
juliaroldi Apr 30, 2024
5c15d3e
Merge branch 'u/juliaroldi/image-span' of https://github.com/microsof…
juliaroldi Apr 30, 2024
f91b48b
port image
juliaroldi Apr 30, 2024
f45bf71
wip
juliaroldi May 2, 2024
69b4204
conflicts
juliaroldi May 2, 2024
ee28ea4
test
juliaroldi May 20, 2024
d5e6775
conflict
juliaroldi May 20, 2024
4766498
WIP
juliaroldi May 21, 2024
3642b10
unit test
juliaroldi May 23, 2024
7ea11d5
test
juliaroldi May 24, 2024
da849be
Merge branch 'master' of https://github.com/microsoft/roosterjs into …
juliaroldi May 24, 2024
98d3520
test
juliaroldi May 24, 2024
cb87afd
test
juliaroldi May 28, 2024
814b54f
remove console.log
juliaroldi May 28, 2024
dd732bb
Merge branch 'master' into u/juliaroldi/port-image
juliaroldi May 28, 2024
d95360c
tests
juliaroldi May 29, 2024
71f830b
Merge branch 'u/juliaroldi/port-image' of https://github.com/microsof…
juliaroldi May 29, 2024
6251d8d
tests
juliaroldi May 29, 2024
ac8790f
changed to protected
juliaroldi May 29, 2024
6d86454
image operations
juliaroldi May 29, 2024
2ec3974
fix test
juliaroldi May 29, 2024
5e1be98
remove code
juliaroldi May 29, 2024
85198f2
Merge branch 'master' into u/juliaroldi/image-edit-operations
juliaroldi May 30, 2024
8b5961c
remove editor
juliaroldi Jun 3, 2024
357c7c7
Merge branch 'u/juliaroldi/image-edit-operations' of https://github.c…
juliaroldi Jun 3, 2024
53b044b
fix test
juliaroldi Jun 3, 2024
4c5963a
WIP
juliaroldi Jun 3, 2024
f86541c
fixes
juliaroldi Jun 4, 2024
3c465c6
fix test
juliaroldi Jun 4, 2024
27792a0
status
juliaroldi Jun 4, 2024
9a9abae
test
juliaroldi Jun 4, 2024
baff339
fix conflicts
juliaroldi Jun 4, 2024
4c8d7eb
add mutate block
juliaroldi Jun 4, 2024
26d6e90
fixes texts
juliaroldi Jun 5, 2024
9dd412a
Merge branch 'master' into u/juliaroldi/image-edit-operations
juliaroldi Jun 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
wip: clean
  • Loading branch information
juliaroldi committed Apr 26, 2024
commit 75bea9e54d20d557f3a8020018bcf28bba427ace
Original file line number Diff line number Diff line change
@@ -85,7 +85,7 @@ const ImageRotateMenuItem: ContextMenuItem<ImageEditMenuItemStringKey, ImageEdit
menuNameImageRotateLeft: 'Left',
menuNameImageRotateRight: 'Right',
},
shouldShow: (editor, node, imageEditor) => {
shouldShow: (_, node, imageEditor) => {
return (
!!imageEditor?.isOperationAllowed('rotate') &&
imageEditor.canRegenerateImage(node as HTMLImageElement)
@@ -110,7 +110,7 @@ const ImageFlipMenuItem: ContextMenuItem<ImageEditMenuItemStringKey, ImageEditor
menuNameImageRotateFlipHorizontally: 'Flip Horizontally',
menuNameImageRotateFlipVertically: 'Flip Vertically',
},
shouldShow: (editor, node, imageEditor) => {
shouldShow: (_, node, imageEditor) => {
return (
!!imageEditor?.isOperationAllowed('rotate') &&
imageEditor.canRegenerateImage(node as HTMLImageElement)
@@ -131,7 +131,7 @@ const ImageFlipMenuItem: ContextMenuItem<ImageEditMenuItemStringKey, ImageEditor
const ImageCropMenuItem: ContextMenuItem<ImageEditMenuItemStringKey, ImageEditor> = {
key: 'menuNameImageCrop',
unlocalizedText: 'Crop image',
shouldShow: (editor, node, imageEditor) => {
shouldShow: (_, node, imageEditor) => {
return (
!!imageEditor?.isOperationAllowed('crop') &&
imageEditor.canRegenerateImage(node as HTMLImageElement)
Original file line number Diff line number Diff line change
@@ -34,12 +34,6 @@ export class TableEditPluginCode extends SimplePluginCode {
}
}

export class CustomReplaceCode extends SimplePluginCode {
constructor() {
super('CustomReplace', 'roosterjsLegacy');
}
}

export class ImageEditPluginCode extends SimplePluginCode {
constructor() {
super('ImageEditPlugin');
6 changes: 1 addition & 5 deletions packages/roosterjs-content-model-dom/lib/index.ts
Original file line number Diff line number Diff line change
@@ -130,14 +130,10 @@ export { retrieveModelFormatState } from './modelApi/editing/retrieveModelFormat
export { getListStyleTypeFromString } from './modelApi/editing/getListStyleTypeFromString';
export { getSegmentTextFormat } from './modelApi/editing/getSegmentTextFormat';

export {
updateImageMetadata,
ImageMetadataFormatDefinition,
} from './modelApi/metadata/updateImageMetadata';
export { updateImageMetadata } from './modelApi/metadata/updateImageMetadata';
export { updateTableCellMetadata } from './modelApi/metadata/updateTableCellMetadata';
export { updateTableMetadata } from './modelApi/metadata/updateTableMetadata';
export { updateListMetadata, ListMetadataDefinition } from './modelApi/metadata/updateListMetadata';
export { validate } from './modelApi/metadata/validate';

export { ChangeSource } from './constants/ChangeSource';
export { BulletListType } from './constants/BulletListType';
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ const NumberDefinition = createNumberDefinition(true);
const BooleanDefinition = createBooleanDefinition(true);

/**
* @internal
* Definition of ImageMetadataFormat
*/
export const ImageMetadataFormatDefinition = createObjectDefinition<Required<ImageMetadataFormat>>({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this used externally?

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { validate } from './validate';
import type { ContentModelWithDataset, Definition } from 'roosterjs-content-model-types';

const EditingInfoDatasetName: string = 'editingInfo';
const EditingInfoDatasetName = 'editingInfo';

/**
* Update metadata of the given model
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ import { getObjectKeys } from '../../domUtils/getObjectKeys';
import type { Definition } from 'roosterjs-content-model-types';

/**
* @internal
* Validate the given object with a type definition object
* @param input The object to validate
* @param def The type definition object used for validation
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import checkEditInfoState, { ImageEditInfoState } from './checkEditInfoState';
import checkEditInfoState from './checkEditInfoState';
import generateDataURL from './generateDataURL';
import getGeneratedImageSize from './generateImageSize';
import { updateImageEditInfo } from './updateImageEditInfo';
@@ -32,16 +32,16 @@ export function applyChange(
const state = checkEditInfoState(editInfo, initEditInfo);

switch (state) {
case ImageEditInfoState.ResizeOnly:
case 'ResizeOnly':
// For resize only case, no need to generate a new image, just reuse the original one
newSrc = editInfo.src || '';
break;
case ImageEditInfoState.SameWithLast:
case 'SameWithLast':
// For SameWithLast case, image may be resized but the content is still the same with last one,
// so no need to create a new image, but just reuse last one
newSrc = previousSrc;
break;
case ImageEditInfoState.FullyChanged:
case 'FullyChanged':
// For other cases (cropped, rotated, ...) we need to create a new image to reflect the change
newSrc = generateDataURL(editingImage ?? image, editInfo);
break;
@@ -78,7 +78,7 @@ export function applyChange(
}
image.src = newSrc;

if (wasResizedOrCropped || state == ImageEditInfoState.FullyChanged) {
if (wasResizedOrCropped || state == 'FullyChanged') {
image.width = generatedImageSize.targetWidth;
image.height = generatedImageSize.targetHeight;
// Remove width/height style so that it won't affect the image size, since style width/height has higher priority
Original file line number Diff line number Diff line change
@@ -24,34 +24,33 @@ const ALL_KEYS = [...ROTATE_CROP_KEYS, ...RESIZE_KEYS];
* State of an edit info object for image editing.
* It is returned by checkEditInfoState() function
*/
export enum ImageEditInfoState {
export type ImageEditInfoState =
/**
* Invalid edit info. It means the given edit info object is either null,
* or not all its member are of correct type
*/
Invalid,
| 'Invalid'

/**
* The edit info shows that it is only potentially edited by resizing action.
* Image is not rotated or cropped, or event not changed at all.
*/
ResizeOnly,
| 'ResizeOnly'

/**
* When compare with another edit info, this value can be returned when both current
* edit info and the other one are not been rotated, and they have same cropping
* percentages. So that they can share the same image src, only width and height
* need to be adjusted.
*/
SameWithLast,
| 'SameWithLast'

/**
* When this value is returned, it means the image is edited by either cropping or
* rotation, or both. Image source can't be reused, need to generate a new image src
* data uri.
*/
FullyChanged,
}
| 'FullyChanged';

/**
* @internal
@@ -68,14 +67,14 @@ export default function checkEditInfoState(
compareTo?: ImageMetadataFormat
): ImageEditInfoState {
if (!editInfo || !editInfo.src || ALL_KEYS.some(key => !isNumber(editInfo[key]))) {
return ImageEditInfoState.Invalid;
return 'Invalid';
} else if (
ROTATE_CROP_KEYS.every(key => areSameNumber(editInfo[key], 0)) &&
!editInfo.flippedHorizontal &&
!editInfo.flippedVertical &&
(!compareTo || (compareTo && editInfo.angleRad === compareTo.angleRad))
) {
return ImageEditInfoState.ResizeOnly;
return 'ResizeOnly';
} else if (
compareTo &&
ROTATE_KEYS.every(key => areSameNumber(editInfo[key], 0)) &&
@@ -84,9 +83,9 @@ export default function checkEditInfoState(
compareTo.flippedHorizontal === editInfo.flippedHorizontal &&
compareTo.flippedVertical === editInfo.flippedVertical
) {
return ImageEditInfoState.SameWithLast;
return 'SameWithLast';
} else {
return ImageEditInfoState.FullyChanged;
return 'FullyChanged';
}
}

4 changes: 3 additions & 1 deletion packages/roosterjs-content-model-plugins/lib/index.ts
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ export { TableEditPlugin } from './tableEdit/TableEditPlugin';
export { PastePlugin } from './paste/PastePlugin';
export { EditPlugin } from './edit/EditPlugin';
export { AutoFormatPlugin, AutoFormatOptions } from './autoFormat/AutoFormatPlugin';

export {
ShortcutBold,
ShortcutItalic,
@@ -29,7 +30,8 @@ export { HyperlinkToolTip } from './hyperlink/HyperlinkToolTip';
export { PickerPlugin } from './picker/PickerPlugin';
export { PickerHelper } from './picker/PickerHelper';
export { PickerSelectionChangMode, PickerDirection, PickerHandler } from './picker/PickerHandler';
export { CustomReplacePlugin, CustomReplace } from './customReplace/CustomReplacePlugin';
export { ImageEditPlugin } from './imageEdit/ImageEditPlugin';
export { ImageEditOptions } from './imageEdit/types/ImageEditOptions';
export { CustomReplacePlugin, CustomReplace } from './customReplace/CustomReplacePlugin';

export { getDOMInsertPointRect } from './pluginUtils/Rect/getDOMInsertPointRect';