Skip to content

Comments

[PE-46] fix: added aspect ratio to resizing#5693

Merged
pushya22 merged 26 commits intopreviewfrom
fix/image-resize-aspect
Sep 30, 2024
Merged

[PE-46] fix: added aspect ratio to resizing#5693
pushya22 merged 26 commits intopreviewfrom
fix/image-resize-aspect

Conversation

@Palanikannan1437
Copy link
Member

@Palanikannan1437 Palanikannan1437 commented Sep 24, 2024

Description

  1. Added aspect ratio to image attributes and I'm no more setting the height on images
  2. Added a smooth blur effect and loading state for images while being uploaded
  3. Added strict types for Pixel values
  4. Restricted the click event on the editor container only to the clicks by the user specifically on the editor container at the bottom by adding padding to it.
  5. Fixed the image insertion position via the Toolbar
  6. Handled the case where image is of old type with width and height attributes are numbers and not pixel value
  7. Handled a case where image doesn't load, showing an error state
  8. Fixed the image resize handler event listener logic to be added only while resizing making it really smooth.
  9. Refactored the entire code for having a better separation between the upload phase and rendering the final image phase.
  10. Added the logic to not allow closing modals while uploading images.
  11. Added the trimming of large file names logic before uploading.
  12. Handled various loading states across the lifecycle of the image upload minimizing layout shifts.
  13. Focusing out of the image carefully depending on what's the current node in selection and the node below it.
  14. Inserting multiple images (while dropping/pasting) carefully taking the last node insertion's status to avoid range errors while inserting.

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced image upload functionality with improved state management and visual feedback for upload failures.
    • Optimized performance for image handling through memoization and refined file upload processes.
  • Bug Fixes

    • Improved error handling during image uploads and loading states.
  • Style

    • Adjusted styling conditions to reflect new image loading states.
  • Documentation

    • Updated internal documentation to reflect changes in image upload and handling functionalities.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 24, 2024

Warning

Rate limit exceeded

@Palanikannan1437 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 5 minutes and 18 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Files that changed from the base of the PR and between 9788599 and 823e11b.

Walkthrough

The changes involve substantial updates to the CustomImageUploader component, enhancing its functionality for image uploads and state management. New props have been added to improve handling of image load failures and to facilitate interaction with the editor's node structure. The component's performance has been optimized with memoization, and the styling has been adjusted to provide visual feedback for image loading states. Overall, these modifications streamline the image upload process within the editor.

Changes

File Path Change Summary
packages/editor/src/core/extensions/custom-image/components/image-uploader.tsx Modified CustomImageUploader to introduce new props for better image upload management, restructure the onUpload callback, and optimize performance with useMemo. Adjusted styling for the failedToLoadImage state.

Possibly related PRs

Suggested labels

🐛bug, 🌐frontend

Suggested reviewers

  • SatishGandham
  • aaryan610
  • sriramveeraghanta

🐰 In the editor's bright, lively space,
Images now find their rightful place.
With clicks and uploads, they dance and twirl,
Enhancing our stories, making them swirl.
So hop along, dear friends, and see,
The magic of images, wild and free! 🌼✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 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 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.

@Palanikannan1437 Palanikannan1437 self-assigned this Sep 30, 2024
@Palanikannan1437 Palanikannan1437 marked this pull request as ready for review September 30, 2024 12:47
@pushya22 pushya22 changed the title fix: added aspect ratio to resizing [PE-46] fix: added aspect ratio to resizing Sep 30, 2024
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: 15

🧹 Outside diff range and nitpick comments (14)
packages/editor/src/core/extensions/custom-image/components/toolbar/root.tsx (1)

13-13: LGTM! Consider adding JSDoc for the new property.

The addition of the aspectRatio property aligns well with the PR objectives of adding aspect ratio support for image attributes. The type is correctly defined as a number, which is appropriate for aspect ratio values.

Consider adding a JSDoc comment to describe the aspectRatio property, its purpose, and any constraints (e.g., positive values only). This would improve code documentation and help other developers understand the property's usage. For example:

image: {
  src: string;
  height: string;
  width: string;
  /** The aspect ratio of the image (width / height). Must be a positive number. */
  aspectRatio: number;
};
packages/editor/src/core/extensions/image/image-component-without-props.tsx (1)

29-31: LGTM! Consider adding documentation for aspectRatio usage.

The addition of the aspectRatio attribute aligns with the PR objectives and enhances the flexibility of image handling. This change eliminates the need to set height on images, as mentioned in the PR summary.

Consider adding a brief comment explaining how the aspectRatio attribute is used and what values it accepts. This would improve the maintainability of the code and help other developers understand its purpose.

Example:

aspectRatio: {
  default: null,
  // Accepts a string in the format "width:height" (e.g., "16:9") or null for no fixed aspect ratio
},
packages/editor/src/core/extensions/custom-image/read-only-custom-image.ts (1)

Line range hint 51-55: Consider adding documentation for fileMap

The addStorage method initializes a fileMap, but its purpose is not immediately clear. Consider adding a brief comment explaining the role of this fileMap in the context of the image extension.

packages/editor/src/core/components/editors/editor-container.tsx (1)

Line range hint 21-58: Consider refactoring for improved code organization

While the current implementation works well, consider the following suggestions to enhance code organization and maintainability:

  1. Extract the editor focus and paragraph insertion logic into separate functions. This would make the handleContainerClick function more concise and easier to understand.

  2. Create a utility function for checking if the current node is within a special block (like lists, tables, etc.). This would reduce code duplication and improve readability.

  3. Consider using more specific error types or including additional error information in the catch block to facilitate easier debugging.

Here's a potential refactoring example:

const isSpecialBlock = (editor: Editor) => {
  return (
    editor.isActive("orderedList") ||
    editor.isActive("bulletList") ||
    editor.isActive("taskItem") ||
    editor.isActive("table") ||
    editor.isActive("blockquote") ||
    editor.isActive("codeBlock")
  );
};

const focusEditorEnd = (editor: Editor) => {
  editor.chain().focus("end", { scrollIntoView: false }).run();
};

const insertNewParagraph = (editor: Editor) => {
  const endPosition = editor.state.doc.content.size;
  editor.chain().insertContentAt(endPosition, { type: "paragraph" }).run();
  editor.chain().setTextSelection(endPosition + 1).run();
};

const handleContainerClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
  if (event.target !== event.currentTarget || !editor || !editor.isEditable) return;
  
  try {
    if (editor.isFocused) return;

    focusEditorEnd(editor);

    const { selection } = editor.state;
    const currentNode = selection.$from.node();

    if (currentNode.content.size === 0 && !isSpecialBlock(editor)) {
      return;
    }

    insertNewParagraph(editor);
  } catch (error) {
    console.error("Error handling container click:", error);
    // Consider adding more specific error handling or logging here
  }
};

This refactoring improves readability and makes the code more modular and easier to maintain.

packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen.tsx (1)

59-66: LGTM: Refactored handleKeyDown for better key event handling

The refactoring of the handleKeyDown function is a good improvement. It consolidates the key event handling logic into a single conditional check, making the code more readable and maintainable. The function correctly handles the Escape, +, =, and - keys for various actions, which is consistent with the PR's goal of refining event listener logic.

Consider using a switch statement or an object lookup for key handling to improve readability further:

const keyActions = {
  'Escape': handleClose,
  '+': handleIncreaseMagnification,
  '=': handleIncreaseMagnification,
  '-': handleDecreaseMagnification
};

if (e.key in keyActions) {
  e.preventDefault();
  e.stopPropagation();
  keyActions[e.key]();
}

This approach can make the code more scalable if you need to add more key handlers in the future.

packages/editor/src/core/helpers/editor-commands.ts (2)

129-148: LGTM with suggestions: Enhance robustness and clarity of insertImage function.

The new insertImage function aligns well with the PR objectives, providing flexible image insertion capabilities. However, consider the following improvements:

  1. Add input validation to prevent potential runtime errors.
  2. Implement error handling to facilitate debugging.
  3. Explicitly define the function's return type for clarity.

Here's a suggested refactoring to address these points:

export const insertImage = ({
  editor,
  event,
  pos,
  file,
  range,
}: {
  editor: Editor;
  event: "insert" | "drop";
  pos?: number | null;
  file?: File;
  range?: Range;
}): boolean => {
  try {
    if (!editor) {
      console.error("Editor is not defined");
      return false;
    }

    if (range) editor.chain().focus().deleteRange(range).run();

    const imageOptions: InsertImageComponentProps = { event };
    if (pos !== undefined && pos !== null) imageOptions.pos = pos;
    if (file) imageOptions.file = file;

    return editor.chain().focus().insertImageComponent(imageOptions).run();
  } catch (error) {
    console.error("Error inserting image:", error);
    return false;
  }
};

This refactored version includes basic input validation, error handling, and an explicit return type.


Line range hint 1-148: Summary: Changes align well with PR objectives for enhanced image handling.

The modifications to this file, particularly the new insertImage function and the updated import, demonstrate a clear focus on improving image handling within the editor. These changes support the PR's goals of enhancing image insertion, including support for different insertion methods (insert, drop) and flexible positioning.

The implementation allows for smooth integration of new image handling features, such as aspect ratio support and improved loading states, as mentioned in the PR objectives. However, to fully realize these objectives, ensure that the InsertImageComponentProps type and the insertImageComponent method (likely defined elsewhere) incorporate all the new features described in the PR summary.

As you continue to develop these features:

  1. Consider implementing unit tests for the insertImage function to ensure its reliability across different scenarios.
  2. Ensure that the error handling and loading states are properly managed throughout the image insertion process, as mentioned in the PR objectives.
  3. If not already done, consider documenting the new image insertion process and any configuration options for other developers who might use this functionality.
packages/editor/src/styles/editor.css (4)

Line range hint 1-54: LGTM! Consider adding a default font size class.

The addition of .large-font, .small-font, .sans-serif, .serif, and .monospace classes provides excellent flexibility for customizing the editor's typography. The use of CSS custom properties for font sizes and line heights is a great approach for maintaining consistency and enabling easy theming.

Consider adding a .default-font class that sets the base font sizes and line heights. This would provide a clear starting point and make it easier to reset to default values if needed.

&.default-font {
  --font-size-h1: 1.5rem;
  --font-size-h2: 1.25rem;
  --font-size-h3: 1.125rem;
  --font-size-h4: 1rem;
  --font-size-h5: 0.875rem;
  --font-size-h6: 0.85rem;
  --font-size-regular: 0.875rem;
  --font-size-list: var(--font-size-regular);
  --font-size-code: var(--font-size-regular);

  --line-height-h1: 2rem;
  --line-height-h2: 1.75rem;
  --line-height-h3: 1.5rem;
  --line-height-h4: 1.375rem;
  --line-height-h5: 1.25rem;
  --line-height-h6: 1.25rem;
  --line-height-regular: 1.375rem;
  --line-height-list: var(--line-height-regular);
  --line-height-code: var(--line-height-regular);
}

Line range hint 128-140: LGTM! Consider adding a focus style for keyboard navigation.

The changes to image styles effectively differentiate between interactive and non-interactive (read-only or loading) images. The hover effect and selection outline for interactive images provide good visual feedback.

To improve accessibility for keyboard users, consider adding a focus style for images. This will help users navigate and interact with images using the keyboard.

&:not(.read-only-image):not(.loading-image) {
  /* ... existing styles ... */

  &:focus-visible {
    outline: 3px solid rgba(var(--color-primary-100));
    filter: brightness(95%);
  }
}

Line range hint 159-245: LGTM! Consider using CSS variables for colors.

The updated task list styles provide a polished and customized appearance for checkboxes. The use of pseudo-elements for the check mark is a great approach. The media query for adjusting the layout on smaller screens is a thoughtful addition.

For better consistency and easier theming, consider using CSS variables for colors instead of hardcoded RGB values. This will make it easier to maintain and update the color scheme across the entire component.

Example:

ul[data-type="taskList"] li > label input[type="checkbox"] {
  /* ... existing styles ... */
  border: 1.5px solid rgb(var(--color-text-100));
  
  &:hover {
    background-color: rgb(var(--color-background-80));
  }

  &:active {
    background-color: rgb(var(--color-background-90));
  }

  /* ... */
}

ul[data-type="taskList"] li[data-checked="true"] > div > p {
  color: rgb(var(--color-text-400));
  /* ... */
}

Line range hint 351-435: LGTM! Consider adding a custom property for font weights.

The updated typography styles provide a well-structured and easily customizable system for headings, paragraphs, and lists. The use of CSS variables for font sizes and line heights is excellent for maintaining consistency and enabling easy theming.

To further improve flexibility, consider adding a custom property for font weights. This would allow for easier customization of font weights across different heading levels and text elements.

Example:

.prose {
  --font-weight-heading: 600;
  --font-weight-body: 400;

  :where(h1):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
    /* ... existing styles ... */
    font-weight: var(--font-weight-heading);
  }

  /* Apply to other heading levels and body text */
}

This change would make it easier to adjust font weights globally or for specific themes without modifying each selector individually.

packages/editor/src/core/extensions/custom-image/components/image-node.tsx (1)

57-79: Simplify conditional rendering for readability

The conditional rendering in the return statement (lines 57-79) is complex and may impact readability.

Consider extracting the condition into a descriptive variable to clarify the intent:

const showImageBlock = (isUploaded || imageFromFileSystem) && !failedToLoadImage;

Then update the JSX:

{showImageBlock ? (
  <CustomImageBlock
    imageFromFileSystem={imageFromFileSystem}
    editorContainer={editorContainer}
    editor={editor}
    failedToLoadImage={failedToLoadImage}
    getPos={getPos}
    node={node}
    setEditorContainer={setEditorContainer}
    setFailedToLoadImage={setFailedToLoadImage}
    selected={selected}
    updateAttributes={updateAttributes}
  />
) : (
  <CustomImageUploader
    editor={editor}
    failedToLoadImage={failedToLoadImage}
    getPos={getPos}
    loadImageFromFileSystem={setImageFromFileSystem}
    node={node}
    setIsUploaded={setIsUploaded}
    selected={selected}
    updateAttributes={updateAttributes}
  />
)}

This enhances readability by clearly expressing the condition's purpose.

packages/editor/src/core/hooks/use-file-upload.ts (1)

36-38: Address the TypeScript error in editor.commands.uploadImage

There's a @ts-expect-error comment indicating a TypeScript error with editor.commands.uploadImage. It's important to resolve this to maintain type safety and prevent potential runtime errors.

Do you need assistance fixing the TypeScript typings for editor.commands.uploadImage? I can help with that or open a GitHub issue to track this task.

packages/editor/src/core/extensions/custom-image/components/image-block.tsx (1)

248-254: Accessibility Enhancement for Resize Handle

The resize handle (<div> at lines 248-254) might not be easily accessible for users relying on keyboard navigation or assistive technologies.

Consider adding appropriate aria attributes and keyboard event handlers to improve accessibility.

             <div
               className={cn(
                 "absolute bottom-0 right-0 translate-y-1/2 translate-x-1/2 size-4 rounded-full bg-custom-primary-100 border-2 border-white cursor-nwse-resize transition-opacity duration-100 ease-in-out",
                 {
                   "opacity-100 pointer-events-auto": isResizing,
                   "opacity-0 pointer-events-none group-hover/image-component:opacity-100 group-hover/image-component:pointer-events-auto":
                     !isResizing,
                 }
               )}
+              role="slider"
+              aria-label="Resize image"
+              tabIndex={0}
               onMouseDown={handleResizeStart}
+              onKeyDown={(e) => {
+                if (e.key === 'Enter' || e.key === ' ') {
+                  handleResizeStart(e);
+                }
+              }}
             />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b1dccf3 and ffcf23e.

📒 Files selected for processing (27)
  • packages/editor/src/core/components/editors/editor-container.tsx (1 hunks)
  • packages/editor/src/core/components/menus/menu-items.ts (2 hunks)
  • packages/editor/src/core/extensions/custom-image/components/image-block.tsx (2 hunks)
  • packages/editor/src/core/extensions/custom-image/components/image-node.tsx (1 hunks)
  • packages/editor/src/core/extensions/custom-image/components/image-uploader.tsx (2 hunks)
  • packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen.tsx (6 hunks)
  • packages/editor/src/core/extensions/custom-image/components/toolbar/root.tsx (1 hunks)
  • packages/editor/src/core/extensions/custom-image/custom-image.ts (5 hunks)
  • packages/editor/src/core/extensions/custom-image/read-only-custom-image.ts (1 hunks)
  • packages/editor/src/core/extensions/drop.tsx (4 hunks)
  • packages/editor/src/core/extensions/extensions.tsx (1 hunks)
  • packages/editor/src/core/extensions/image/image-component-without-props.tsx (2 hunks)
  • packages/editor/src/core/extensions/image/image-extension-without-props.tsx (0 hunks)
  • packages/editor/src/core/extensions/slash-commands.tsx (2 hunks)
  • packages/editor/src/core/helpers/editor-commands.ts (2 hunks)
  • packages/editor/src/core/hooks/use-editor.ts (3 hunks)
  • packages/editor/src/core/hooks/use-file-upload.ts (4 hunks)
  • packages/editor/src/core/plugins/image/image-upload-handler.ts (0 hunks)
  • packages/editor/src/core/plugins/image/index.ts (0 hunks)
  • packages/editor/src/core/plugins/image/upload-image.ts (0 hunks)
  • packages/editor/src/core/plugins/image/utils/index.ts (0 hunks)
  • packages/editor/src/core/plugins/image/utils/placeholder.ts (0 hunks)
  • packages/editor/src/styles/editor.css (1 hunks)
  • web/core/components/editor/rich-text-editor/rich-text-editor.tsx (1 hunks)
  • web/core/components/inbox/content/issue-root.tsx (1 hunks)
  • web/core/components/issues/issue-detail/main-content.tsx (1 hunks)
  • web/core/components/issues/peek-overview/issue-detail.tsx (1 hunks)
💤 Files with no reviewable changes (6)
  • packages/editor/src/core/extensions/image/image-extension-without-props.tsx
  • packages/editor/src/core/plugins/image/image-upload-handler.ts
  • packages/editor/src/core/plugins/image/index.ts
  • packages/editor/src/core/plugins/image/upload-image.ts
  • packages/editor/src/core/plugins/image/utils/index.ts
  • packages/editor/src/core/plugins/image/utils/placeholder.ts
✅ Files skipped from review due to trivial changes (2)
  • web/core/components/issues/issue-detail/main-content.tsx
  • web/core/components/issues/peek-overview/issue-detail.tsx
🔇 Additional comments (38)
packages/editor/src/core/extensions/custom-image/components/toolbar/root.tsx (1)

13-13: Verify usage of aspectRatio in related components

While the addition of aspectRatio is correct, it's not directly used in this component. Ensure that:

  1. The ImageFullScreenAction component properly utilizes this new property.
  2. Any other components or functions that use the image object are updated to handle the new aspectRatio property if necessary.

To verify the usage of aspectRatio in related components, run the following script:

This script will help identify where and how the aspectRatio property is being used, allowing us to ensure consistent implementation across related components.

packages/editor/src/core/extensions/image/image-component-without-props.tsx (3)

Line range hint 1-53: Summary: Changes enhance image handling, but require verification.

The modifications to CustomImageComponentWithoutProps align well with the PR objectives, particularly in adding aspect ratio support and streamlining the component. Key points:

  1. The new aspectRatio attribute provides more flexibility in image rendering.
  2. Removal of ReactNodeViewRenderer and addNodeView simplifies the component structure.
  3. The addition of UploadImageExtensionStorage suggests improved upload functionality.

To ensure these changes don't introduce unintended side effects:

  1. Verify the usage of UploadImageExtensionStorage.
  2. Check the impact of removing addNodeView on image rendering.
  3. Consider adding documentation for the aspectRatio attribute.
  4. Update or add unit tests to cover the new behavior.

Overall, these changes appear to enhance the functionality and maintainability of the image component.


4-4: LGTM! Verify the usage of the new import.

The import changes align with the removal of the addNodeView method and the introduction of image upload functionality. The new import UploadImageExtensionStorage suggests enhanced capabilities for managing image uploads.

To ensure the new import is used correctly, please run the following script:

#!/bin/bash
# Description: Verify the usage of UploadImageExtensionStorage in the file

# Test: Search for UploadImageExtensionStorage usage
rg --type typescript "UploadImageExtensionStorage" packages/editor/src/core/extensions/image/image-component-without-props.tsx

Line range hint 1-53: Verify the impact of removing addNodeView on image rendering.

The removal of the addNodeView method, as mentioned in the AI summary, aligns with the PR objectives. However, it's important to ensure that this change doesn't negatively impact image rendering in the editor.

Please run the following script to check for any remaining references to addNodeView and to verify the new image rendering mechanism:

Ensure that the image rendering still works as expected after this change. Consider adding unit tests or updating existing ones to cover the new rendering behavior.

packages/editor/src/core/extensions/custom-image/read-only-custom-image.ts (2)

Line range hint 1-58: Verify implementation of PR objectives

The PR objectives mention several features such as a smooth blur effect, loading state, and error handling for image uploads. These are not visible in this file. Could you please confirm if these features are implemented in the CustomImageNode component or elsewhere in the codebase?

#!/bin/bash
# Search for implementations of blur effect, loading state, and error handling
rg --type typescript -e 'blur.*effect' -e 'loading.*state' -e 'error.*handling' packages/editor/src

30-32: LGTM: Addition of aspectRatio attribute

The addition of the aspectRatio attribute aligns with the PR objective of adding aspect ratio support for image attributes. Setting the default value to null provides flexibility in usage.

However, I noticed that the height attribute is still present with a default value of "auto". The PR summary mentions eliminating the need to set height on images. Could you clarify if the height attribute is still necessary?

web/core/components/editor/rich-text-editor/rich-text-editor.tsx (1)

54-54: LGTM: Added bottom padding to improve user interaction.

The addition of the pb-3 class to the container's className is a good change. This bottom padding aligns with the PR objective of restricting click events on the editor container to user-initiated clicks. It should help prevent accidental interactions near the bottom edge of the editor, improving the overall user experience.

packages/editor/src/core/components/editors/editor-container.tsx (2)

21-22: Excellent improvement to click handling!

The changes to the handleContainerClick function effectively address the PR objective of restricting click events on the editor container to user-initiated clicks. Here's why this is a great improvement:

  1. The updated function signature now includes the event parameter, allowing access to crucial event information.
  2. The new condition if (event.target !== event.currentTarget) return; ensures that the function only proceeds if the click was directly on the container, preventing unintended behavior when clicking on child elements.

These changes enhance the precision of the click handling, improving the overall user experience and reducing potential bugs related to misplaced cursor focus or unintended paragraph insertions.


Line range hint 1-85: Summary of the review

The changes made to the EditorContainer component, particularly in the handleContainerClick function, effectively address the PR objectives. The implementation restricts click events to user-initiated clicks on the container, enhancing the precision of editor interactions.

Key points from the review:

  1. The changes are approved and align well with the PR objectives.
  2. The new event handling improves user experience and reduces potential bugs.
  3. Suggestions for further refactoring have been provided to enhance code organization and maintainability.

Overall, this is a solid improvement to the editor's functionality. The suggested refactoring, if implemented, would further enhance the code quality without changing the core functionality.

packages/editor/src/core/extensions/extensions.tsx (2)

Line range hint 1-168: Summary of changes in CoreEditorExtensions

The modification in this file is focused and aligns well with the PR objectives. It updates the way the image upload status is accessed within the Placeholder extension configuration. This change is likely part of a broader refactoring effort to improve image handling across the application.

The isolated nature of this change, with no other modifications to the file, suggests that related changes might be present in other files. It would be beneficial to review these related files to ensure consistency in the new approach to image upload status management.


152-152: Approve the update to image upload status check.

The change from editor.storage.image.uploadInProgress to editor.storage.imageComponent.uploadInProgress aligns with the PR objectives of refactoring the image handling process. This update likely reflects a restructuring of how the image upload status is stored in the editor's storage.

To ensure this change is consistent across the codebase, please run the following script:

This script will help identify any inconsistencies in how the image upload status is accessed throughout the codebase.

✅ Verification successful

Further Verification Needed on Image Upload Status Usage

The previous script encountered an error due to unrecognized file types. Please run the updated script below to verify the usage of the new image upload status storage path:


Further Verification Needed on Image Upload Status Usage

The previous script failed to recognize the file types. Please run the updated script below to verify the usage of the new image upload status storage path:


Image Upload Status Check Successfully Updated

The search results confirm that the old storage path editor.storage.image.uploadInProgress is no longer present in the codebase. All usages of the image upload status now consistently reference editor.storage.imageComponent.uploadInProgress, aligning with the PR objectives of refactoring the image handling process.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of the new image upload status storage path

# Test 1: Check for any remaining instances of the old storage path
echo "Checking for old storage path usage:"
rg --type typescript --type tsx 'editor\.storage\.image\.uploadInProgress'

# Test 2: Verify the usage of the new storage path
echo "Checking new storage path usage:"
rg --type typescript --type tsx 'editor\.storage\.imageComponent\.uploadInProgress'

Length of output: 390


Script:

#!/bin/bash
# Description: Verify the usage of the new image upload status storage path

# Test 1: Check for any remaining instances of the old storage path
echo "Checking for old storage path usage:"
rg 'editor\.storage\.image\.uploadInProgress' --type tsx --type ts

# Test 2: Verify the usage of the new storage path
echo "Checking new storage path usage:"
rg 'editor\.storage\.imageComponent\.uploadInProgress' --type tsx --type ts

Length of output: 360


Script:

#!/bin/bash
# Description: Verify the usage of the new image upload status storage path

# Test 1: Check for any remaining instances of the old storage path
echo "Checking for old storage path usage:"
rg 'editor\.storage\.image\.uploadInProgress' -g '*.ts' -g '*.tsx'

# Test 2: Verify the usage of the new storage path
echo "Checking new storage path usage:"
rg 'editor\.storage\.imageComponent\.uploadInProgress' -g '*.ts' -g '*.tsx'

Length of output: 681

web/core/components/inbox/content/issue-root.tsx (1)

130-130: LGTM. Verify visual impact and update PR description.

The styling changes to the IssueDescriptionInput component look good. The removal of !mb-6 and addition of border-none seem to be intentional styling adjustments.

Please verify the visual impact of these changes:

  1. Ensure that removing the bottom margin (!mb-6) doesn't negatively affect the layout or spacing between elements.
  2. Confirm that removing the border (border-none) aligns with the intended design.

Consider updating the PR description to include this styling change, as it's not mentioned in the current objectives.

packages/editor/src/core/components/menus/menu-items.ts (2)

26-26: LGTM: Good modularization practice.

The addition of insertImage to the imports is a positive change. It suggests that this function has been moved to a separate file, which improves code organization and promotes reusability.


197-197: LGTM: Improved modularity, but verify usage.

The update to the ImageItem function improves code modularity by delegating the image insertion logic to a separate insertImage function. This change enhances maintainability and readability.

Please run the following script to verify that all usages of ImageItem have been updated to accommodate this change:

This script will help identify any locations where ImageItem is used and might need updating, as well as any remaining direct uses of setImageUpload that should now use insertImage.

✅ Verification successful

Please run the following updated script to verify that all usages of ImageItem have been updated accordingly:


Please run the following updated script to verify that all usages of ImageItem have been updated accordingly:


Verified: All usages of ImageItem are correctly updated.

The verification confirms that the ImageItem function is properly updated in menu-items.ts and there are no outdated setImageUpload usages remaining in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usages of ImageItem that might need updating

# Search for ImageItem usages
echo "Searching for ImageItem usages:"
rg --type typescript --type javascript "ImageItem\(" -C 3

# Search for potential outdated usages of setImageUpload
echo "Searching for potential outdated setImageUpload usages:"
rg --type typescript --type javascript "setImageUpload.*event:\s*['\"]insert['\"]" -C 3

Length of output: 417


Script:

# Description: Check for usages of ImageItem that might need updating

# Search for ImageItem usages
echo "Searching for ImageItem usages:"
rg --type ts --type tsx "ImageItem\(" -C 3

# Search for potential outdated usages of setImageUpload
echo "Searching for potential outdated setImageUpload usages:"
rg --type ts --type tsx "setImageUpload.*event:\s*['\"]insert['\"]" -C 3

Length of output: 373


Script:

# Description: Check for usages of ImageItem that might need updating

# Search for ImageItem usages
echo "Searching for ImageItem usages:"
rg --glob "*.ts" --glob "*.tsx" "ImageItem\(" -C 3

# Search for potential outdated setImageUpload usages
echo "Searching for potential outdated setImageUpload usages:"
rg --glob "*.ts" --glob "*.tsx" "setImageUpload.*event:\s*['\"]insert['\"]" -C 3

Length of output: 775

packages/editor/src/core/extensions/custom-image/components/toolbar/full-screen.tsx (7)

11-11: LGTM: Added aspectRatio property to Props type

The addition of the aspectRatio property to the image object in the Props type is a good change. It aligns with the PR objective of adding aspect ratio support for image attributes and follows TypeScript best practices by explicitly defining the type for new properties.


21-21: LGTM: Updated props destructuring

The change in destructuring the image object to include aspectRatio instead of height is consistent with the PR objective. This modification supports the goal of using aspect ratio for image sizing, eliminating the need for explicit height values.


24-25: LGTM: Added modalRef for improved modal management

The addition of modalRef using useRef is a good practice. This ref will likely be used to manage the modal's DOM reference, which is crucial for implementing features like closing the modal when clicking outside. This change aligns with the PR's goal of enhancing user interaction.


70-78: LGTM: Added handleClickOutside for improved modal interaction

The addition of the handleClickOutside function is a great improvement to the user experience. It allows users to close the modal by clicking outside of it, which is a common and expected behavior in modern web applications. The function correctly uses the modalRef to check if the click target is the modal backdrop, following React best practices for handling click outside events.


81-86: LGTM: Optimized useEffect for conditional event listener

The modification of the useEffect hook is a good optimization. By conditionally adding and removing the keydown event listener based on the isFullScreenEnabled state, the code ensures that the listener is only active when necessary. This prevents unnecessary event handling when the modal is not open and correctly cleans up the listener when the component unmounts or when isFullScreenEnabled becomes false. This change aligns with React best practices for managing side effects and event listeners.


100-100: LGTM: Improved modal interaction and styling

The changes to the modal container and bottom control bar are good improvements:

  1. Adding the onClick={handleClickOutside} and ref={modalRef} to the modal container (line 100) implements the click-outside functionality, enhancing user interaction.
  2. The addition of bg-black to the bottom control bar (line 117) improves its visibility and the overall user experience.

These modifications align well with the PR's objectives of enhancing user interaction and making visual improvements.

Also applies to: 117-117


Line range hint 1-158: Overall assessment: Excellent improvements to the ImageFullScreenAction component

The changes made to this file significantly enhance the functionality and user experience of the full-screen image viewer component. Key improvements include:

  1. Addition of aspect ratio support for image sizing
  2. Refined event handling for keyboard interactions
  3. Implementation of click-outside functionality for closing the modal
  4. Optimized event listener management
  5. Improved styling for better visibility

These changes align well with the PR objectives and follow React and TypeScript best practices. The code is now more maintainable, performant, and user-friendly. Great job on these improvements!

packages/editor/src/core/helpers/editor-commands.ts (1)

7-7: LGTM: Import change aligns with enhanced image handling.

The change from UploadImage to InsertImageComponentProps reflects the shift in image insertion management described in the PR objectives. This new import likely provides a more structured approach to handling image insertion properties.

packages/editor/src/core/extensions/slash-commands.tsx (1)

230-230: Improved modularity for image insertion logic.

The change to use a separate insertImage function enhances code modularity and maintainability. This aligns well with the PR objectives related to image handling improvements.

To ensure the correctness of this change, please verify the implementation of the insertImage function in the "@/helpers/editor-commands" file. Specifically, check that it correctly handles the range parameter to maintain the expected insertion behavior.

packages/editor/src/core/extensions/drop.tsx (2)

23-23: ⚠️ Potential issue

Fix incorrect event parameter in insertImages call within handlePaste

In the handlePaste method, the event parameter in the insertImages function call is set to "drop". Since this is a paste event, it should be "insert" to accurately reflect the type of event, as per the allowed values "insert" or "drop".

Apply this diff to fix the event parameter:

-                  insertImages({ editor: this.editor, files: imageFiles, initialPos: pos, event: "drop" });
+                  insertImages({ editor: this.editor, files: imageFiles, initialPos: pos, event: "insert" });

Likely invalid or redundant comment.


56-56: ⚠️ Potential issue

Remove unnecessary async keyword from insertImages function

The insertImages function is declared with the async keyword, but there are no await statements within its body. Since the function does not perform any asynchronous operations, the async keyword can be removed to simplify the code.

Apply this diff to remove the async keyword:

-const insertImages = async ({
+const insertImages = ({

Likely invalid or redundant comment.

packages/editor/src/core/extensions/custom-image/components/image-node.tsx (1)

45-50: Ensure stability of node.attrs reference in useEffect dependency

In the useEffect hook (lines 45-50), you're depending on node.attrs.src. If node.attrs is a new object on each render, this could cause unnecessary re-renders.

Check if node.attrs is a stable reference. If it's recreated on each render, consider restructuring your dependencies:

  • Use node.attrs.src directly in the dependency array.
  • Ensure that node.attrs remains the same object if its properties haven't changed.
packages/editor/src/core/hooks/use-file-upload.ts (1)

19-19: Verify if direct mutation of editor.storage.imageComponent.uploadInProgress is safe

Directly mutating editor.storage.imageComponent.uploadInProgress may cause issues if imageComponent is intended to be immutable or if there are side effects associated with its state changes. It's important to ensure that this mutation is safe and doesn't violate any intended design patterns.

To confirm whether it's safe to mutate uploadInProgress directly, you can check if there are setter methods or if the property is meant to be mutable.

Run the following script to search for uploadInProgress usage:

This will help determine if direct assignment is acceptable or if you should use a setter method.

✅ Verification successful

Attempting verification with corrected file type.


Direct mutation of editor.storage.imageComponent.uploadInProgress is safe.

After reviewing the definitions and usages of uploadInProgress across the codebase, it is clear that direct mutations are intentional and do not violate any design patterns or immutability constraints.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for definitions and usages of `uploadInProgress` in the codebase.

# Test: Find how `uploadInProgress` is defined and used.
rg --type typescript 'uploadInProgress' -A 5 -B 5

Length of output: 84


Script:

#!/bin/bash
# Description: Search for definitions and usages of `uploadInProgress` in the codebase using the correct file type.

rg --type ts 'uploadInProgress' -A 5 -B 5

Length of output: 6436

packages/editor/src/core/extensions/custom-image/custom-image.ts (6)

14-18: Definition of InsertImageComponentProps enhances type safety.

The new type InsertImageComponentProps clearly defines the properties for image insertion, improving code clarity and maintainability.


23-23: Updated command signature utilizes InsertImageComponentProps correctly.

By adopting the InsertImageComponentProps type in the insertImageComponent command, the code gains better type safety and readability.


29-31: Function getImageComponentImageFileMap is implemented appropriately.

The use of optional chaining safely handles cases where imageComponent might be undefined, preventing potential runtime errors.


63-65: Added aspectRatio attribute for improved image control.

Including the aspectRatio attribute allows for better handling of image resizing while maintaining the correct proportions.


116-116: Initialization of uploadInProgress enhances state management.

Adding uploadInProgress to the storage helps in effectively tracking the upload state of images.


Line range hint 122-147: insertImageComponent command handles events correctly.

The command properly distinguishes between "insert" and "drop" events, managing the fileMap accordingly to ensure correct image insertion behavior.

packages/editor/src/core/extensions/custom-image/components/image-block.tsx (2)

202-207: Potential Infinite Re-rendering on Image Load Error

In the onError handler for the <img> element, you set failedToLoadImage state to true. However, without proper handling, this might cause the component to re-render indefinitely if the image source is invalid.

Check whether setting failedToLoadImage triggers a state change that re-attempts to load the image, causing an infinite loop.

Consider adding a condition to prevent repeated loading attempts for the same erroneous source.


126-133: Ensure Aspect Ratio Is Defined Before Resizing

In the handleResize function, you check for size.aspectRatio before proceeding. However, there might be cases where size.aspectRatio is null, which would prevent resizing from working correctly.

Run the following script to check if size.aspectRatio can ever be null during resize operations:

packages/editor/src/core/hooks/use-editor.ts (3)

63-63: Initialization of savedSelection state variable

The addition of the savedSelection state using useState<Selection | null>(null) is appropriate for tracking the editor's selection.


207-207: Ensure consistency in isEditorReadyToDiscard method

The isEditorReadyToDiscard method now checks editorRef.current?.storage.imageComponent.uploadInProgress === false. Verify that this change aligns with the overall upload status tracking and that all dependent logic reflects this update.

Run the following script to check for inconsistent references:

#!/bin/bash
# Description: Search for old references in the `isEditorReadyToDiscard` implementations.

rg 'isEditorReadyToDiscard.*editorRef\.current\?\..*\.storage\.image\.uploadInProgress'

110-110: Verify the correct usage of imageComponent.uploadInProgress

The change from editor.storage.image.uploadInProgress to editor.storage.imageComponent.uploadInProgress indicates a shift in how image upload status is tracked. Ensure that imageComponent is the correct storage module and that all other references have been updated accordingly.

Run the following script to identify any remaining references to the old property:

And confirm the usage of the new property:

✅ Verification successful

Verification Successful: Correct usage of imageComponent.uploadInProgress confirmed. All references to the old property have been updated accordingly.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find usages of the old image upload progress property.

rg 'editor\.storage\.image\.uploadInProgress'

Length of output: 89


Script:

#!/bin/bash
# Description: Verify the correct usage of the new imageComponent upload progress property.

rg 'editor\.storage\.imageComponent\.uploadInProgress'

Length of output: 433


Script:

#!/bin/bash
# Description: Re-verify usages of the old image upload progress property.

rg 'editor\.storage\.image\.uploadInProgress'

Length of output: 47

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

🧹 Outside diff range and nitpick comments (1)
packages/editor/src/core/extensions/custom-image/components/image-uploader.tsx (1)

Line range hint 122-160: Approve JSX structure with suggestion for text content

The component's JSX structure is well-implemented:

  1. Conditional styling provides clear visual feedback.
  2. Drag and drop functionality is correctly set up.
  3. The hidden file input is properly implemented and referenced.

Consider refactoring the text content logic for better readability:

const getDisplayText = () => {
  if (failedToLoadImage) return "Error loading image";
  if (isImageBeingUploaded || existingFile) return "Uploading...";
  if (draggedInside) return "Drop image here";
  return "Add an image";
};

// In JSX
<div className="text-base font-medium">
  {getDisplayText()}
</div>

This refactoring simplifies the nested ternary operators, making the code more readable and maintainable.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ffcf23e and 9788599.

📒 Files selected for processing (1)
  • packages/editor/src/core/extensions/custom-image/components/image-uploader.tsx (2 hunks)
🔇 Additional comments (5)
packages/editor/src/core/extensions/custom-image/components/image-uploader.tsx (5)

1-35: Improved component architecture and responsibilities

The changes to imports and props demonstrate a significant architectural improvement:

  1. The component now handles more of the upload process internally, reducing the burden on parent components.
  2. The addition of useCallback, useEffect, and useMemo hooks suggests optimized rendering and side-effect management.
  3. The node prop allows direct interaction with the editor's data model, enabling more precise updates.

These changes should lead to better performance and easier maintenance.


79-108: Well-implemented memoization and side effects for file upload

The use of useMemo for meta data and existing file, combined with the useEffect hooks for managing file uploads, is well-implemented:

  1. Memoization prevents unnecessary recalculations.
  2. The upload logic efficiently handles both dropped and inserted files.
  3. The hasTriggeredFilePickerRef prevents redundant file picker triggers.

This implementation should provide a smooth and efficient upload experience.


Line range hint 110-120: Approve onFileChange implementation

The onFileChange callback is correctly implemented:

  1. It properly handles file selection from the input.
  2. File validity is checked before uploading, preventing invalid files from being processed.
  3. The useCallback dependency array is correct, including only the uploadFile function.

This implementation ensures efficient and safe file handling.


129-130: Approve error state styling

The addition of the failedToLoadImage condition to the className is a good improvement:

  1. It provides clear visual feedback when an image fails to load.
  2. The red color scheme effectively communicates the error state.
  3. The implementation is consistent with the component's overall styling approach.

This change enhances the user experience by clearly indicating when there's an issue with image loading.


137-137: Approve click handler for improved user interaction

The addition of the onClick handler to the main div is a good improvement:

  1. It allows the entire component area to trigger file selection.
  2. This improves user experience by providing a larger clickable area.
  3. The implementation correctly uses the ref to trigger a click on the hidden file input.

This change makes the component more intuitive and easier to use.

[uploadFile]
);

const getDisplayMessage = useCallback(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not Important: Doesn't look like this requires useCallback since it is just being consumed in the same component

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants