From cb183bc88258083fa6991bf3ebe2891378355615 Mon Sep 17 00:00:00 2001 From: Luci Date: Sun, 25 May 2025 16:33:02 +0700 Subject: [PATCH 1/2] fix embedded block is deleted after input a special Vietnamese character --- ..._editor_state_text_input_client_mixin.dart | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/lib/src/editor/raw_editor/raw_editor_state_text_input_client_mixin.dart b/lib/src/editor/raw_editor/raw_editor_state_text_input_client_mixin.dart index e35489b75..2dc3356e5 100644 --- a/lib/src/editor/raw_editor/raw_editor_state_text_input_client_mixin.dart +++ b/lib/src/editor/raw_editor/raw_editor_state_text_input_client_mixin.dart @@ -1,3 +1,4 @@ +import 'dart:io'; import 'dart:ui' show lerpDouble; import 'package:flutter/cupertino.dart'; @@ -224,6 +225,45 @@ mixin RawEditorStateTextInputClientMixin on EditorState return; } + // On iOS, we need to handle a special case where the user deletes two + // characters that are not part of the text, such as the zero-width space + // character (\uFFFC) used for embedding images. In this case, we don't + // want to send an update to the native side, as it would cause the + // text to be deleted and the cursor to move incorrectly. + // This is a workaround for an issue where the iOS text input client + // does not handle the deletion of these characters correctly. + if (Platform.isIOS) { + final lastKnownValue = _lastKnownRemoteTextEditingValue; + + if ( + //verify that lastKnownValue is not null + lastKnownValue != null && + // verify that lastKnownValue selection extentOffset is more than + // 2 characters away from baseOffset + lastKnownValue.selection.extentOffset - + lastKnownValue.selection.baseOffset == + 2 && + // verify that the lastKnownValue text length is more than 2 + // characters away from the value text length + lastKnownValue.text.length - value.text.length == 2 && + value.selection.isCollapsed && + value.selection.affinity == TextAffinity.downstream && + value.selection.isDirectional == false) { + // take the last two characters from the last known value + final deletedText = lastKnownValue.text.substring( + value.selection.baseOffset, + value.selection.baseOffset + 2, + ); + + // if the deleted text starts with the zero-width embed character, + // we don't want to send an update to the native side + // as it will cause the embedded block to be deleted + if (deletedText.startsWith('\uFFFC')) { + return; + } + } + } + final effectiveLastKnownValue = _lastKnownRemoteTextEditingValue!; _lastKnownRemoteTextEditingValue = value; final oldText = effectiveLastKnownValue.text; From b2c5648beac53af0159cfaa15adaf25221b32216 Mon Sep 17 00:00:00 2001 From: Luci Date: Mon, 26 May 2025 12:47:14 +0700 Subject: [PATCH 2/2] fix: handle special case for Vietnamese input on iOS to prevent accidental deletion of embedded objects --- ..._editor_state_text_input_client_mixin.dart | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/src/editor/raw_editor/raw_editor_state_text_input_client_mixin.dart b/lib/src/editor/raw_editor/raw_editor_state_text_input_client_mixin.dart index 2dc3356e5..cb42b2509 100644 --- a/lib/src/editor/raw_editor/raw_editor_state_text_input_client_mixin.dart +++ b/lib/src/editor/raw_editor/raw_editor_state_text_input_client_mixin.dart @@ -225,13 +225,18 @@ mixin RawEditorStateTextInputClientMixin on EditorState return; } - // On iOS, we need to handle a special case where the user deletes two - // characters that are not part of the text, such as the zero-width space - // character (\uFFFC) used for embedding images. In this case, we don't - // want to send an update to the native side, as it would cause the - // text to be deleted and the cursor to move incorrectly. - // This is a workaround for an issue where the iOS text input client - // does not handle the deletion of these characters correctly. + // On iOS, we need to handle a special case where user input modifies a previous word. + // For example, in Vietnamese keyboard with the Telex input method, + // the word "dinh" becomes "định" when the user types "d". + // iOS handles this by deleting several characters + // from the end of the word to the beginning (plus one extra character) + // and then re-inserting the updated characters. + // + // The issue arises when the word is adjacent to an embedded object (e.g., an embedded block). + // iOS may accidentally remove the embedded object character (\uFFFC) + // during this replacement process. To prevent this, + // we should skip updating the text value + // if the change affects the starting character and is next to an embedded block. if (Platform.isIOS) { final lastKnownValue = _lastKnownRemoteTextEditingValue;