flutter-quill icon indicating copy to clipboard operation
flutter-quill copied to clipboard

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

Open honmaple opened this issue 1 year ago • 5 comments

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),
);

honmaple avatar Sep 30 '24 10:09 honmaple

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 avatar Sep 30 '24 11:09 EchoEllet

This is still an issue, why it was closed?

EchoEllet avatar Oct 02 '24 08:10 EchoEllet

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

honmaple avatar Oct 02 '24 09:10 honmaple

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

realth000 avatar Nov 01 '24 16:11 realth000

I say we should add an id for the nodes. This way, if the offset fails at least we can remove it using another method that might be more effective.

CatHood0 avatar Mar 01 '25 18:03 CatHood0