Skip to content

Conversation

@egordidenko
Copy link
Contributor

@egordidenko egordidenko commented Jan 14, 2025

Description

Checklist

Summary by CodeRabbit

  • New Features

    • Added a configuration option for a mask href in the cloud image editor.
    • Introduced mask functionality with custom positioning and rendering.
  • Style

    • Updated CSS to disable mouse interactions for mask elements.
    • Adjusted body height to full viewport.
  • Documentation

    • Updated type definitions to support new mask configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 14, 2025

Walkthrough

The pull request introduces a new configuration option cloudImageEditorMaskHref for the cloud image editor, enabling the addition of a mask image. This feature is implemented across multiple files, including the configuration, type definitions, CSS, and the core CropFrame component. The changes add methods to create and update a mask image within the SVG context of the image editor, with supporting configuration and type updates to facilitate this new functionality.

Changes

File Change Summary
blocks/CloudImageEditor/src/CropFrame.js Added _createMask and _updateMask private methods, modified _render method, added configuration subscription for cloudImageEditorMaskHref
blocks/CloudImageEditor/src/css/common.css Added CSS rule to disable pointer events for .uc-cloud-mask elements
blocks/Config/initialConfig.js Added cloudImageEditorMaskHref configuration property initialized to null
blocks/Config/normalizeConfigValue.js Added mapping for cloudImageEditorMaskHref with asString normalization
demo/cloud-image-editor.html Added body height rule set to 100vh
types/exported.d.ts Added cloudImageEditorMaskHref property to ConfigType interface

Sequence Diagram

sequenceDiagram
    participant Config as Configuration
    participant CropFrame as CropFrame Component
    participant SVG as SVG Element

    Config->>CropFrame: Set cloudImageEditorMaskHref
    CropFrame->>CropFrame: _createMask(href)
    CropFrame->>SVG: Create/Update mask image
    CropFrame->>CropFrame: _updateMask()
    CropFrame->>SVG: Adjust mask position and dimensions
Loading

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • JIRA integration encountered authorization issues. Please disconnect and reconnect the integration in the CodeRabbit UI.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between ea48c88 and d1173ba.

📒 Files selected for processing (6)
  • blocks/CloudImageEditor/src/CropFrame.js (2 hunks)
  • blocks/CloudImageEditor/src/css/common.css (1 hunks)
  • blocks/Config/initialConfig.js (1 hunks)
  • blocks/Config/normalizeConfigValue.js (1 hunks)
  • demo/cloud-image-editor.html (1 hunks)
  • types/exported.d.ts (9 hunks)
✅ Files skipped from review due to trivial changes (2)
  • blocks/Config/initialConfig.js
  • types/exported.d.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • blocks/CloudImageEditor/src/css/common.css
  • blocks/Config/normalizeConfigValue.js
  • demo/cloud-image-editor.html
  • blocks/CloudImageEditor/src/CropFrame.js
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (javascript)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
blocks/Config/initialConfig.js (1)

76-77: LGTM! Consider fixing the typo in mediaRecorerOptions

The initialization of maskHrefCloudEditor as null is appropriate. However, I noticed an existing typo in the property name above it: mediaRecorerOptions should be mediaRecorderOptions.

-  mediaRecorerOptions: null,
+  mediaRecorderOptions: null,
types/exported.d.ts (1)

270-271: Add JSDoc documentation for the new property

Please add JSDoc documentation for the maskHrefCloudEditor property to maintain consistency with other properties in the interface.

+  /**
+   * URL of the mask image to be applied in the cloud editor.
+   * @default null
+   */
   maskHrefCloudEditor: string | null;
blocks/CloudImageEditor/src/CropFrame.js (1)

475-490: Add error handling for SVG attribute updates.

The _updateMask method should handle potential failures when updating SVG attributes.

Apply this diff to improve error handling:

 _updateMask() {
   let cropBox = this.$['*cropBox'];

   if (!cropBox || !this._frameImage) {
     return;
   }

   let { x, y, width, height } = cropBox;

+  try {
     setSvgNodeAttrs(this._frameImage, {
       x,
       y,
       height,
       width,
     });
+  } catch (error) {
+    console.error('Failed to update mask attributes:', error);
+  }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7715385 and e02fa08.

📒 Files selected for processing (7)
  • blocks/CloudImageEditor/src/CropFrame.js (2 hunks)
  • blocks/CloudImageEditor/src/css/common.css (1 hunks)
  • blocks/Config/Config.js (2 hunks)
  • blocks/Config/initialConfig.js (1 hunks)
  • blocks/Config/normalizeConfigValue.js (1 hunks)
  • demo/cloud-image-editor.html (1 hunks)
  • types/exported.d.ts (1 hunks)
🔇 Additional comments (4)
blocks/Config/normalizeConfigValue.js (1)

175-175: LGTM!

The mapping of maskHrefCloudEditor to asString is appropriate for handling string | null type values.

blocks/CloudImageEditor/src/CropFrame.js (1)

496-496: LGTM!

The addition of _updateMask() to the render cycle ensures the mask stays synchronized with other UI updates.

demo/cloud-image-editor.html (1)

33-33: LGTM!

Setting height: 100vh ensures the editor container fills the viewport height correctly.

blocks/CloudImageEditor/src/css/common.css (1)

1194-1196: LGTM!

Setting pointer-events: none correctly prevents the mask from intercepting mouse events, allowing interactions with underlying elements.

* 'fileValidators',
* 'collectionValidators',
* 'mediaRecorerOptions',
* 'maskHrefCloudEditor',
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove maskHrefCloudEditor from complexConfigKeys

The maskHrefCloudEditor property is of type string | null, which can be safely passed as an attribute. The complexConfigKeys array is specifically for properties that are objects or functions and cannot be passed as attributes.

 * @type {[
 *   'metadata',
 *   'localeDefinitionOverride',
 *   'secureUploadsSignatureResolver',
 *   'secureDeliveryProxyUrlResolver',
 *   'iconHrefResolver',
 *   'fileValidators',
 *   'collectionValidators',
-*   'mediaRecorerOptions',
-*   'maskHrefCloudEditor',
+*   'mediaRecorerOptions'
 * ]}
 */
export const complexConfigKeys = [
  'metadata',
  'localeDefinitionOverride',
  'secureUploadsSignatureResolver',
  'secureDeliveryProxyUrlResolver',
  'iconHrefResolver',
  'fileValidators',
  'collectionValidators',
-  'mediaRecorerOptions',
-  'maskHrefCloudEditor',
+  'mediaRecorerOptions'
];

Also applies to: 37-37

Comment on lines 538 to 542
this.subConfigValue('maskHrefCloudEditor', (maskHref) => {
if (maskHref) {
this._createMask(maskHref);
}
});
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Handle mask removal when maskHref becomes null.

The subscription should clean up the mask when the maskHref config is cleared.

Apply this diff to handle mask removal:

 this.subConfigValue('maskHrefCloudEditor', (maskHref) => {
   if (maskHref) {
     this._createMask(maskHref);
+  } else if (this._frameImage) {
+    this._frameImage.remove();
+    this._frameImage = null;
   }
 });

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +449 to +473
/**
* @private
* @param {String} href
*/
_createMask(href) {
if (this._frameImage) {
this._frameImage.setAttribute('href', href);
return;
}

let svg = this.ref['svg-el'];
let fr = document.createDocumentFragment();

let imageNode = createSvgNode('image', {
href,
});

imageNode.setAttribute('class', 'uc-cloud-mask');

fr.appendChild(imageNode);

svg.appendChild(fr);

this._frameImage = imageNode;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add input validation and error handling.

The _createMask method should validate the href parameter and handle potential SVG operation failures.

Apply this diff to improve the implementation:

 _createMask(href) {
+  if (!href || typeof href !== 'string') {
+    console.warn('Invalid href provided to _createMask');
+    return;
+  }
+
   if (this._frameImage) {
+    // Clean up old image resources before updating href
+    this._frameImage.removeAttribute('href');
     this._frameImage.setAttribute('href', href);
     return;
   }

   let svg = this.ref['svg-el'];
+  if (!svg) {
+    console.error('SVG element not found');
+    return;
+  }
   let fr = document.createDocumentFragment();

   let imageNode = createSvgNode('image', {
     href,
   });

   imageNode.setAttribute('class', 'uc-cloud-mask');

   fr.appendChild(imageNode);

   svg.appendChild(fr);

   this._frameImage = imageNode;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* @private
* @param {String} href
*/
_createMask(href) {
if (this._frameImage) {
this._frameImage.setAttribute('href', href);
return;
}
let svg = this.ref['svg-el'];
let fr = document.createDocumentFragment();
let imageNode = createSvgNode('image', {
href,
});
imageNode.setAttribute('class', 'uc-cloud-mask');
fr.appendChild(imageNode);
svg.appendChild(fr);
this._frameImage = imageNode;
}
/**
* @private
* @param {String} href
*/
_createMask(href) {
if (!href || typeof href !== 'string') {
console.warn('Invalid href provided to _createMask');
return;
}
if (this._frameImage) {
// Clean up old image resources before updating href
this._frameImage.removeAttribute('href');
this._frameImage.setAttribute('href', href);
return;
}
let svg = this.ref['svg-el'];
if (!svg) {
console.error('SVG element not found');
return;
}
let fr = document.createDocumentFragment();
let imageNode = createSvgNode('image', {
href,
});
imageNode.setAttribute('class', 'uc-cloud-mask');
fr.appendChild(imageNode);
svg.appendChild(fr);
this._frameImage = imageNode;
}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
blocks/CloudImageEditor/src/CropFrame.js (2)

449-473: ⚠️ Potential issue

Add input validation and error handling.

The _createMask method needs improved validation and error handling.

Apply this diff to improve the implementation:

 _createMask(href) {
+  if (!href || typeof href !== 'string') {
+    console.warn('Invalid href provided to _createMask');
+    return;
+  }
+
   if (this._frameImage) {
+    // Clean up old image resources before updating href
+    this._frameImage.removeAttribute('href');
     this._frameImage.setAttribute('href', href);
     return;
   }

   let svg = this.ref['svg-el'];
+  if (!svg) {
+    console.error('SVG element not found');
+    return;
+  }
   let fr = document.createDocumentFragment();

   let imageNode = createSvgNode('image', {
     href,
   });

   imageNode.setAttribute('class', 'uc-cloud-mask');

   fr.appendChild(imageNode);

   svg.appendChild(fr);

   this._frameImage = imageNode;
 }

538-542: ⚠️ Potential issue

Handle mask removal when maskHref becomes null.

The subscription should clean up the mask when the maskHref config is cleared.

Apply this diff to handle mask removal:

 this.subConfigValue('cloudImageEditorMaskHref', (maskHref) => {
   if (maskHref) {
     this._createMask(maskHref);
+  } else if (this._frameImage) {
+    this._frameImage.remove();
+    this._frameImage = null;
   }
 });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e02fa08 and c3c3d14.

📒 Files selected for processing (5)
  • blocks/CloudImageEditor/src/CropFrame.js (2 hunks)
  • blocks/Config/Config.js (2 hunks)
  • blocks/Config/initialConfig.js (1 hunks)
  • blocks/Config/normalizeConfigValue.js (1 hunks)
  • types/exported.d.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • types/exported.d.ts
  • blocks/Config/initialConfig.js
  • blocks/Config/Config.js
  • blocks/Config/normalizeConfigValue.js
🔇 Additional comments (1)
blocks/CloudImageEditor/src/CropFrame.js (1)

491-496: LGTM!

The addition of _updateMask() to the render cycle is appropriate and follows the existing pattern.

@egordidenko egordidenko force-pushed the feat/cloud-editor-implement-mask branch from 5fabc2c to 0652cf9 Compare January 23, 2025 09:08
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🔭 Outside diff range comments (1)
blocks/CloudImageEditor/src/CropFrame.js (1)

Line range hint 566-570: Add cleanup for mask resources.

The destroyCallback should clean up mask-related resources to prevent memory leaks.

 destroyCallback() {
   super.destroyCallback();
 
+  if (this._frameImage) {
+    this._frameImage.remove();
+    this._frameImage = null;
+  }
+
   document.removeEventListener('pointermove', this._handlePointerMove);
   document.removeEventListener('pointerup', this._handlePointerUp);
 }
🧹 Nitpick comments (1)
blocks/CloudImageEditor/src/CropFrame.js (1)

482-489: Maintain consistent property order.

The property order in setSvgNodeAttrs differs from the object destructuring order. Maintain consistency for better code readability.

-    setSvgNodeAttrs(this._frameImage, {
-      x,
-      y,
-      height,
-      width,
-    });
+    setSvgNodeAttrs(this._frameImage, {
+      x,
+      y,
+      width,
+      height,
+    });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c3c3d14 and 0652cf9.

📒 Files selected for processing (6)
  • blocks/CloudImageEditor/src/CropFrame.js (2 hunks)
  • blocks/CloudImageEditor/src/css/common.css (1 hunks)
  • blocks/Config/initialConfig.js (1 hunks)
  • blocks/Config/normalizeConfigValue.js (1 hunks)
  • demo/cloud-image-editor.html (1 hunks)
  • types/exported.d.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • demo/cloud-image-editor.html
  • types/exported.d.ts
  • blocks/Config/initialConfig.js
  • blocks/CloudImageEditor/src/css/common.css
  • blocks/Config/normalizeConfigValue.js
🔇 Additional comments (4)
blocks/CloudImageEditor/src/CropFrame.js (4)

449-473: Add input validation and error handling.

The _createMask method needs validation and error handling improvements.

Previous review comment still applies. The implementation should:

  1. Validate the href parameter
  2. Handle potential SVG operation failures
  3. Clean up old image resources before updates
  4. Validate SVG element existence

475-490: Add validation and optimize mask updates.

The _updateMask method needs property validation and performance optimization.

Previous review comment still applies. The implementation should:

  1. Validate cropBox properties
  2. Cache current values to avoid unnecessary updates

496-496: LGTM!

The _updateMask call is appropriately placed in the render cycle.


538-542: ⚠️ Potential issue

Handle mask cleanup and validate maskHref.

The subscription needs improvements:

  1. Clean up the mask when maskHref becomes null
  2. Add validation for maskHref value
 this.subConfigValue('cloudImageEditorMaskHref', (maskHref) => {
+  if (typeof maskHref !== 'string' && maskHref !== null) {
+    console.warn('Invalid maskHref value:', maskHref);
+    return;
+  }
   if (maskHref) {
     this._createMask(maskHref);
+  } else if (this._frameImage) {
+    this._frameImage.remove();
+    this._frameImage = null;
   }
 });

Likely invalid or redundant comment.

@egordidenko egordidenko force-pushed the feat/cloud-editor-implement-mask branch from 0652cf9 to ea48c88 Compare February 24, 2025 19:30
@egordidenko egordidenko force-pushed the feat/cloud-editor-implement-mask branch from ea48c88 to d1173ba Compare April 25, 2025 07:57
@egordidenko egordidenko changed the title feat(cloud-editor): added image mask feat(cloud-editor): added image mask in the cloud image editor Apr 28, 2025
@egordidenko egordidenko merged commit 1863a5d into main Apr 28, 2025
3 checks passed
@egordidenko egordidenko deleted the feat/cloud-editor-implement-mask branch April 28, 2025 13:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants