singerdmx / flutter-quill

Rich text editor for Flutter
https://pub.dev/packages/flutter_quill
MIT License
2.6k stars 839 forks source link

Embed.offset or documentOffset always be zero, so that I could't remove custom EmbedWidget #2303

Open honmaple opened 1 month ago

honmaple commented 1 month ago

Is there an existing issue for this?

The question

I have a custom embed widget.

controller.replaceText(
      selection.baseOffset,
      selection.extentOffset - selection.baseOffset,
      BlockEmbed.custom(CustomBlockEmbed("tag", "sometag")),
      TextSelection.collapsed(offset: selection.baseOffset + 1),
    );
class TagEmbedBuilder extends EmbedBuilder {
  @override
  String get key => "tag";

  @override
  Widget build(
    BuildContext context,
    QuillController controller,
    Embed node,
    bool readOnly,
    bool inline,
    TextStyle textStyle,
  ) {
    final tag = node.value.data as String;
    Widget child = Container(
      padding: const EdgeInsets.fromLTRB(6, 2, 6, 2),
      decoration: BoxDecoration(
        color: Theme.of(context).primaryColor,
        borderRadius: const BorderRadius.all(Radius.circular(4)),
      ),
      child: Text(
        "# $tag",
        style: const TextStyle(
          color: Colors.white,
          fontSize: 12,
        ),
      ),
    );
    return Text.rich(
      WidgetSpan(
        alignment: PlaceholderAlignment.middle,
        child: (readOnly)
            ? child
            : PopupMenuButton(
                position: PopupMenuPosition.under,
                child: child,
                itemBuilder: (context) {
                  final offset = node.documentOffset;
                  return [
                    PopupMenuItem(
                      height: 16 * 2,
                      child: const Text("edit"),
                      onTap: () async {
                      },
                    ),
                    PopupMenuItem(
                      height: 16 * 2,
                      child: const Text("remove"),
                      onTap: () {
                      },
                    ),
                  ];
                },
              ),
      ),
    );
  }
}

But when I want to remove this embed, I must move cursor before at this embed, and then use

final offset = getEmbedNode(
  controller,
  controller.selection.start,
).offset;
controller.replaceText(
  offset,
  1,
  '',
  TextSelection.collapsed(offset: offset),
);

How could I get offset without move cursor? The node.offset or node.documentOffset always be zero

controller.replaceText(
  node.offset,
  // or use node.documentOffset,
  1,
  '',
  TextSelection.collapsed(offset: node.offset - 1),
);
EchoEllet commented 1 month ago

It seems that neither the old example nor the current one covers this, we should definitely document that info somewhere clear so everyone can access them.

Might want to have them in Custom Embed Blocks or somewhere related to the controller and update, and delete operations with clearer examples. As for now, I'm unable to take a look at this issue as I'm working on others.

It seems that some things in the video embed (from flutter_quill_extensions) are simply not possible or not documented properly, for example deleting an image or custom embed from the editor doesn't call onImageRemoved and is only callable when remove it using the remove button.

We may need to change some things on how the embed blocks work but it won't soon.

EchoEllet commented 1 month ago

This is still an issue, why it was closed?

honmaple commented 1 month ago

@EchoEllet I'm using Embeddable("tag", "sometag") instead of BlockEmbed.custom(CustomBlockEmbed("tag", "sometag")), node.offset or node.documentOffset has been worked.

realth000 commented 3 weeks ago

Could we reopen this?

Seems the direct cause is the reassignment at https://github.com/singerdmx/flutter-quill/blob/de94bc2c385e4161a94629d631818568598c3cf4/lib/src/editor/widgets/text/text_line.dart#L210C7-L210C18