updateEditingValue method Null safety

  1. @override
void updateEditingValue(
  1. TextEditingValue value
)
override

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);
  if (diff.deleted.isEmpty && diff.inserted.isEmpty) {
    widget.controller.updateSelection(value.selection, ChangeSource.LOCAL);
  } else {
    widget.controller.replaceText(
        diff.start, diff.deleted.length, diff.inserted, value.selection);
  }
}