zefyr icon indicating copy to clipboard operation
zefyr copied to clipboard

[1.0-dev] Paste from clipboard doesn't work on mobile for

Open yamsergey opened this issue 4 years ago • 3 comments

Hello.

I don't know if it's already planned to fix or I'm doing wrong by testing 1.0-dev directly, but there is an issue with Paste on mobile.

Steps to Reproduce

  1. Open Zefyr on a mobile device
  2. Long press on the field and wait option's pop-up menu appears
  3. Tap on paste option

Expected: Clipboard's content appears in the field

Actual: Nothing happening

Reason

It seems to be missed there https://github.com/memspace/zefyr/blob/faebf0e21a8dee8ada5393b34f7c1ee36ea3f3fe/packages/zefyr/lib/src/widgets/editor_selection_delegate_mixin.dart#L13-L17 . Selection has been updated, but the content hasn't been changed.

yamsergey avatar Oct 09 '20 09:10 yamsergey

I did some investigation in an attempt to fix it 😇

Just want to share here in case you are interested.

The fun part, TextSelectionControll handles not only text selections 😂 It also handles Cut and Paste and it will use TextSelectionDelegate in a slightly unexpected way to handle the actions:

  1. Obtain current text and selection from the delegate
  2. Based on the data from the delegate and info in the clipboard it will compile new text
  3. Set new text and selection to the delegate

As a result, I had a problem with preserving formatting if I will use TexEditingValue as it supposed to be. Instead, I came up with a solution where I'm trying to guess what was the change and then handle the action. The solution is not pretty bu it works and looks like this :

  @override
  set textEditingValue(TextEditingValue value) {
    if (value.text == textEditingValue.text) {
      widget.controller.updateSelection(value.selection);
    } else {
      __setEditingValue(value);
    }
  }

  void __setEditingValue(TextEditingValue value) async {
    if (await __isItCut(value)) {
      widget.controller.replaceText(
        textEditingValue.selection.start,
        textEditingValue.text.length - value.text.length,
        '',
        selection: value.selection,
      );
    } else {
      final TextEditingValue value = textEditingValue;
      final ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain);
      if (data != null) {
        final length = textEditingValue.selection.end - textEditingValue.selection.start;
        widget.controller.replaceText(
          value.selection.start,
          length,
          data.text,
          selection: value.selection,
        );
      }
    }
  }

  Future<bool> __isItCut(TextEditingValue value) async {
    final ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain);

    return textEditingValue.text.length - value.text.length == data.text.length;
  }

P.S. Also, there is a related issue https://github.com/pulyaevskiy/quill-delta-dart/issues/18

yamsergey avatar Oct 17 '20 20:10 yamsergey

Did anyone get an update on this? Trying to figure out how to fix it, but I can't seem to get it working in version 1.0.0-dev2 :)

Albert-Jan avatar Dec 17 '20 09:12 Albert-Jan

I did some investigation in an attempt to fix it 😇

Just want to share here in case you are interested.

The fun part, TextSelectionControll handles not only text selections 😂 It also handles Cut and Paste and it will use TextSelectionDelegate in a slightly unexpected way to handle the actions:

  1. Obtain current text and selection from the delegate
  2. Based on the data from the delegate and info in the clipboard it will compile new text
  3. Set new text and selection to the delegate

As a result, I had a problem with preserving formatting if I will use TexEditingValue as it supposed to be. Instead, I came up with a solution where I'm trying to guess what was the change and then handle the action. The solution is not pretty bu it works and looks like this :

  @override
  set textEditingValue(TextEditingValue value) {
    if (value.text == textEditingValue.text) {
      widget.controller.updateSelection(value.selection);
    } else {
      __setEditingValue(value);
    }
  }

  void __setEditingValue(TextEditingValue value) async {
    if (await __isItCut(value)) {
      widget.controller.replaceText(
        textEditingValue.selection.start,
        textEditingValue.text.length - value.text.length,
        '',
        selection: value.selection,
      );
    } else {
      final TextEditingValue value = textEditingValue;
      final ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain);
      if (data != null) {
        final length = textEditingValue.selection.end - textEditingValue.selection.start;
        widget.controller.replaceText(
          value.selection.start,
          length,
          data.text,
          selection: value.selection,
        );
      }
    }
  }

  Future<bool> __isItCut(TextEditingValue value) async {
    final ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain);

    return textEditingValue.text.length - value.text.length == data.text.length;
  }

P.S. Also, there is a related issue pulyaevskiy/quill-delta-dart#18

Thanks @yamsergey, The solution you shared really worked. If someone else facing the issue can try this solution.

TheAlphamerc avatar Jun 28 '21 09:06 TheAlphamerc