Skip to content

Conversation

@asjqkkkk
Copy link
Collaborator

@asjqkkkk asjqkkkk commented Apr 30, 2025

Feature Preview


PR Checklist

  • My code adheres to AppFlowy's Conventions
  • I've listed at least one issue that this PR fixes in the description above.
  • I've added a test(s) to validate changes in this PR, or this PR only contains semantic changes.
  • All existing tests are passing.

Summary by Sourcery

Fix an issue with editing links that could potentially break text styles in the document editor

Bug Fixes:

  • Preserve text styles (bold, italic, underline) when editing or removing links

Enhancements:

  • Improve link editing functionality to maintain existing text attributes

Tests:

  • Added integration test to verify link editing with styled text
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Apr 30, 2025

Reviewer's Guide

This pull request fixes a bug where text styles (like bold, italic) were lost when creating or removing links. The implementation retrieves existing text attributes before modifying link-specific attributes, ensuring other styles are preserved. Link removal logic was also refactored into an EditorState extension, and an integration test was added to verify the fix.

File-Level Changes

Change Details Files
Modified link handling to preserve existing text attributes.
  • Added _getAttribute helper to fetch attributes for a given selection.
  • Updated applyLink to merge existing attributes with new link attributes.
  • Updated removeLink to fetch existing attributes and remove only link-specific ones.
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/desktop_toolbar/link/link_extension.dart
Refactored link removal logic.
  • Added removeAndReplaceLink extension method to EditorState to handle link removal while preserving attributes.
  • Removed the local onRemoveAndReplaceLink helper from _LinkHoverTriggerState.
  • Updated _LinkHoverTriggerState to call the new removeAndReplaceLink extension method.
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/desktop_toolbar/link/link_extension.dart
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/desktop_toolbar/link/link_hover_menu.dart
Added integration test for editing links with styles.
  • Added edit link text with style test case.
  • Verified that applying styles, adding a link, and removing the link preserves the original styles.
frontend/appflowy_flutter/integration_test/desktop/document/document_toolbar_test.dart

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @asjqkkkk - I've reviewed your changes - here's some feedback:

  • Consider consolidating the getAttribute logic to avoid duplication between the test and the extension.
  • The pattern of fetching existing attributes before formatting or replacing text is repeated; explore if this could be further refactored within the extension.
Here's what I looked at during the review
  • 🟡 General issues: 1 issue found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
if (start > startOffset) break;
final length = op.length;
if (start + length > startOffset) {
attributes = op.attributes ?? {};
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion (bug_risk): Consider cloning the attributes to avoid unintended mutation.

Since _getAttribute returns op.attributes by reference, removing keys will mutate shared state. Clone the map first (e.g., with Map.from) before modifying.

Suggested change
attributes = op.attributes ?? {};
attributes = op.attributes != null ? Map.from(op.attributes) : {};
if (node == null) {
return;
}
final attributes = _getAttribute(node, selection);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we're not getting all the attributes from the selection. For example:

Before:

http://appflowy.io <- (add one more o here)

After:

http://appflowy.ioo The result should be ioo without extra formatting.

We have a slice attributes function that gets the attributes based on the index. appflowyEditorSliceAttributes

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yes, the logic about getting Attributes is not correct, I need to adjust it

@asjqkkkk asjqkkkk marked this pull request as draft May 20, 2025 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants