zefyr
zefyr copied to clipboard
[1.0-dev] Paste from clipboard doesn't work on mobile for
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
- Open Zefyr on a mobile device
- Long press on the field and wait option's pop-up menu appears
- 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.
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:
- Obtain current text and selection from the delegate
- Based on the data from the delegate and info in the clipboard it will compile new text
- 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
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 :)
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 handlesCut
andPaste
and it will useTextSelectionDelegate
in a slightly unexpected way to handle the actions:
- Obtain current text and selection from the delegate
- Based on the data from the delegate and info in the clipboard it will compile new text
- 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.