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

Bug: key backward cause ImageNode delete unexpected #6851

Closed
emsurezhang opened this issue Nov 21, 2024 · 3 comments · Fixed by #7006
Closed

Bug: key backward cause ImageNode delete unexpected #6851

emsurezhang opened this issue Nov 21, 2024 · 3 comments · Fixed by #7006

Comments

@emsurezhang
Copy link

截屏2024-11-21 21 01 37 In the playground, I insert an ImageNode and press enter to start a new ParagraphNode. The cursor is at ParagraphNode which key is 4. Now I press backward and expect only the ParagraphNode key 4 is deleted. But the result is the ImageNode is deleted too. 截屏2024-11-21 21 07 09
@emsurezhang
Copy link
Author

emsurezhang commented Nov 21, 2024

In LexicalSelection.ts removeText() function, I simply remove the node.remove line, it workes fine.

/**
   * Removes the text in the Selection, adjusting the EditorState accordingly.
   */
  removeText(): void {
    if (this.isCollapsed()) {
      return;
    }
    const {anchor, focus} = this;
    const selectedNodes = this.getNodes();
    const firstPoint = this.isBackward() ? focus : anchor;
    const lastPoint = this.isBackward() ? anchor : focus;
    let firstNode = firstPoint.getNode();
    let lastNode = lastPoint.getNode();
    const firstBlock = $getAncestor(firstNode, INTERNAL_$isBlock);
    const lastBlock = $getAncestor(lastNode, INTERNAL_$isBlock);
    // If a token is partially selected then move the selection to cover the whole selection
    if (
      $isTextNode(firstNode) &&
      firstNode.isToken() &&
      firstPoint.offset < firstNode.getTextContentSize()
    ) {
      firstPoint.offset = 0;
    }
    if (lastPoint.offset > 0 && $isTextNode(lastNode) && lastNode.isToken()) {
      lastPoint.offset = lastNode.getTextContentSize();
    }

    selectedNodes.forEach((node) => {
      if (
        !$hasAncestor(firstNode, node) &&
        !$hasAncestor(lastNode, node) &&
        node.getKey() !== firstNode.getKey() &&
        node.getKey() !== lastNode.getKey()
      ) {
        console.log("remove node", node.getKey())
        **// node.remove();**
      }
    });

    const fixText = (node: TextNode, del: number) => {
      if (node.getTextContent() === '') {
        node.remove();
      } else if (del !== 0 && $isTokenOrSegmented(node)) {
        const textNode = $createTextNode(node.getTextContent());
        textNode.setFormat(node.getFormat());
        textNode.setStyle(node.getStyle());
        return node.replace(textNode);
      }
    };
    if (firstNode === lastNode && $isTextNode(firstNode)) {
      const del = Math.abs(focus.offset - anchor.offset);
      firstNode.spliceText(firstPoint.offset, del, '', true);
      fixText(firstNode, del);
      return;
    }
    if ($isTextNode(firstNode)) {
      const del = firstNode.getTextContentSize() - firstPoint.offset;
      firstNode.spliceText(firstPoint.offset, del, '');
      firstNode = fixText(firstNode, del) || firstNode;
    }
    if ($isTextNode(lastNode)) {
      lastNode.spliceText(0, lastPoint.offset, '');
      lastNode = fixText(lastNode, lastPoint.offset) || lastNode;
    }
    if (firstNode.isAttached() && $isTextNode(firstNode)) {
      firstNode.selectEnd();
    } else if (lastNode.isAttached() && $isTextNode(lastNode)) {
      lastNode.selectStart();
    }

    // Merge blocks
    const bothElem = $isElementNode(firstBlock) && $isElementNode(lastBlock);
    if (bothElem && firstBlock !== lastBlock) {
      firstBlock.append(...lastBlock.getChildren());
      lastBlock.remove();
      lastPoint.set(firstPoint.key, firstPoint.offset, firstPoint.type);
    }
  }

is there any suggestion to fix it ?

@emsurezhang
Copy link
Author

I think the real reason is after delete ParagraphNode the selection should be collapsed, so in the remove.text function

if (this.isCollapsed()) {
      return;
}

will be return, the node.remove() will not run.

@emsurezhang
Copy link
Author

update:
in LexicalSelection.ts file, change the native selection move mode from "extend" to "move", cause isCollapsed is true.
at line 1781:
this.modify('extend', isBackward, 'character'); => this.modify('move', isBackward, 'character');

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

Successfully merging a pull request may close this issue.

2 participants