updateEditingValue method
Requests that this client update its editing state to the given value.
The new value
is treated as user input and thus may subject to input
formatting.
Implementation
@override
void updateEditingValue(TextEditingValue value) {
if (!shouldCreateInputConnection) {
return;
}
if (_sentRemoteValues.contains(value)) {
/// There is a race condition in Flutter text input plugin where sending
/// updates to native side too often results in broken behavior.
/// TextInputConnection.setEditingValue is an async call to native side.
/// For each such call native side _always_ sends an update which triggers
/// this method (updateEditingValue) with the same value we've sent it.
/// If multiple calls to setEditingValue happen too fast and we only
/// track the last sent value then there is no way for us to filter out
/// automatic callbacks from native side.
/// Therefore we have to keep track of all values we send to the native
/// side and when we see this same value appear here we skip it.
/// This is fragile but it's probably the only available option.
_sentRemoteValues.remove(value);
return;
}
if (_lastKnownRemoteTextEditingValue == value) {
// There is no difference between this value and the last known value.
return;
}
// Check if only composing range changed.
if (_lastKnownRemoteTextEditingValue!.text == value.text &&
_lastKnownRemoteTextEditingValue!.selection == value.selection) {
// This update only modifies composing range. Since we don't keep track
// of composing range we just need to update last known value here.
// This check fixes an issue on Android when it sends
// composing updates separately from regular changes for text and
// selection.
_lastKnownRemoteTextEditingValue = value;
return;
}
final effectiveLastKnownValue = _lastKnownRemoteTextEditingValue!;
_lastKnownRemoteTextEditingValue = value;
final oldText = effectiveLastKnownValue.text;
final text = value.text;
final cursorPosition = value.selection.extentOffset;
final diff = getDiff(oldText, text, cursorPosition);
widget.controller.replaceText(
diff.start, diff.deleted.length, diff.inserted, value.selection);
}