From 8eefb526e73a04b52d6755ed33b88fd5e4f4ea27 Mon Sep 17 00:00:00 2001 From: Matthias Beerens <3512339+Matthiee@users.noreply.github.com> Date: Fri, 28 Apr 2023 10:21:15 +0200 Subject: [PATCH] Add crop mode API methods --- src/controllers/FrameController.ts | 38 +++++++++++++++++++ src/tests/controllers/FrameController.test.ts | 30 +++++++++++++++ src/types/FrameTypes.ts | 15 ++++++++ 3 files changed, 83 insertions(+) diff --git a/src/controllers/FrameController.ts b/src/controllers/FrameController.ts index 720a09be..0bdc3c74 100644 --- a/src/controllers/FrameController.ts +++ b/src/controllers/FrameController.ts @@ -618,4 +618,42 @@ export class FrameController { const res = await this.#editorAPI; return res.setFrameBlendMode(frameId, blendMode).then((result) => getEditorResponseData(result)); }; + + /** + * This method will make the specified image frame go into cropping mode. + * @param frameId The ID of a specific image frame + * @returns + */ + enterCropMode = async (frameId: Id) => { + const res = await this.#editorAPI; + return res.enterCropMode(frameId).then((result) => getEditorResponseData(result)); + }; + + /** + * This method will exit cropping mode while saving the applied crop. + * @returns + */ + applyCropMode = async () => { + const res = await this.#editorAPI; + return res.applyCropMode().then((result) => getEditorResponseData(result)); + }; + + /** + * This method will reset the currently applied crop mode and apply the last selected fit mode again. + * @param frameId The ID of a specific image frame + * @returns + */ + resetCropMode = async (frameId: Id) => { + const res = await this.#editorAPI; + return res.resetCropMode(frameId).then((result) => getEditorResponseData(result)); + }; + + /** + * This method will exit cropping mode without saving the applied crop. + * @returns + */ + cancelCropMode = async () => { + const res = await this.#editorAPI; + return res.cancelCropMode().then((result) => getEditorResponseData(result)); + }; } diff --git a/src/tests/controllers/FrameController.test.ts b/src/tests/controllers/FrameController.test.ts index 5509c72a..16f4531c 100644 --- a/src/tests/controllers/FrameController.test.ts +++ b/src/tests/controllers/FrameController.test.ts @@ -62,6 +62,10 @@ const mockedEditorApi: EditorAPI = { setFrameBlendMode: async () => getEditorResponseData(castToEditorResponse(null)), renameFrame: async () => getEditorResponseData(castToEditorResponse(null)), setImageSource: async () => getEditorResponseData(castToEditorResponse(null)), + enterCropMode: async () => getEditorResponseData(castToEditorResponse(null)), + applyCropMode: async () => getEditorResponseData(castToEditorResponse(null)), + resetCropMode: async () => getEditorResponseData(castToEditorResponse(null)), + cancelCropMode: async () => getEditorResponseData(castToEditorResponse(null)), }; beforeEach(() => { @@ -111,6 +115,10 @@ beforeEach(() => { jest.spyOn(mockedEditorApi, 'setFrameBlendMode'); jest.spyOn(mockedEditorApi, 'renameFrame'); jest.spyOn(mockedEditorApi, 'setImageSource'); + jest.spyOn(mockedEditorApi, 'enterCropMode'); + jest.spyOn(mockedEditorApi, 'applyCropMode'); + jest.spyOn(mockedEditorApi, 'resetCropMode'); + jest.spyOn(mockedEditorApi, 'cancelCropMode'); frameId = mockSelectFrame.frameId; }); @@ -356,6 +364,28 @@ describe('FrameController', () => { expect(mockedEditorApi.setFrameBlendMode).toHaveBeenCalledTimes(1); expect(mockedEditorApi.setFrameBlendMode).toHaveBeenCalledWith(frameId, BlendMode.darken); }); + + it('Should be possible to enter cropping mode on a specific frame', async () => { + await mockedFrameController.enterCropMode(frameId); + expect(mockedEditorApi.enterCropMode).toHaveBeenCalledTimes(1); + expect(mockedEditorApi.enterCropMode).toHaveBeenCalledWith(frameId); + }); + + it('Should be possible to apply the current image crop to the frame', async () => { + await mockedFrameController.applyCropMode(); + expect(mockedEditorApi.applyCropMode).toHaveBeenCalledTimes(1); + }); + + it('Should be possible to reset cropping mode on a specific frame', async () => { + await mockedFrameController.resetCropMode(frameId); + expect(mockedEditorApi.resetCropMode).toHaveBeenCalledTimes(1); + expect(mockedEditorApi.resetCropMode).toHaveBeenCalledWith(frameId); + }); + + it('Should be possible to cancel the current image crop', async () => { + await mockedFrameController.cancelCropMode(); + expect(mockedEditorApi.cancelCropMode).toHaveBeenCalledTimes(1); + }); }); describe('ImageFrameSource manipulations', () => { diff --git a/src/types/FrameTypes.ts b/src/types/FrameTypes.ts index fa42610d..62a22caa 100644 --- a/src/types/FrameTypes.ts +++ b/src/types/FrameTypes.ts @@ -15,6 +15,7 @@ export type FrameLayoutType = { scaleY: PropertyState; included: PropertyState; fitMode: PropertyState; + hasImageCrop: PropertyState; minCopyfitting: PropertyState; maxCopyfitting: PropertyState; enableCopyfitting: PropertyState; @@ -59,6 +60,7 @@ export type ImageFrame = { src?: ImageFrameSource; blendMode: BlendMode; constrainProportions: boolean; + crop?: CropSettings | NoCropSettings; }; export type ShapeFrame = { @@ -102,6 +104,19 @@ export type TextFrame = { constrainProportions: boolean; }; +export type CropSettings = { + left: number; + top: number; + width: number; + height: number; + rotationDegrees: number; + type: 'default'; +}; + +export type NoCropSettings = { + type: 'noCrop'; +}; + export enum ImageSourceTypeEnum { url = 'url', variable = 'variable',