syncImeBufferToFragment method
void
syncImeBufferToFragment()
Implementation
void syncImeBufferToFragment() {
if (connectionManager.connection == null ||
!connectionManager.connection!.attached) {
return;
}
if (state.isComposing) return;
final doc = _document;
if (doc == null) return;
final currentFragId = doc.cursor.focusId.isNotEmpty
? doc.cursor.focusId
: doc.cursor.anchorId;
if (currentFragId != state.lastSyncedFragmentId) {
_resetPlatformBuffer();
}
state.lastSyncedFragmentId = currentFragId;
if (!_shouldSyncBuffer) {
return;
}
final text = _getCurrentFragmentText();
if (text == null) {
_resetPlatformBuffer();
return;
}
final cursor = doc.cursor;
final isSingleFragSelection =
!cursor.isCollapsed && cursor.anchorId == cursor.focusId;
final isMultiFragSelection =
!cursor.isCollapsed && cursor.anchorId != cursor.focusId;
final offset = _getCursorOffsetInFragment();
final bool usePlaceholder =
defaultTargetPlatform == TargetPlatform.iOS &&
cursor.isCollapsed &&
offset == 0 &&
!text.startsWith(_emptyFragmentPlaceholder);
final syncedText = usePlaceholder
? '$_emptyFragmentPlaceholder$text'
: text;
final syncedOffset = usePlaceholder
? 1
: offset.clamp(0, syncedText.length);
final TextSelection syncedSelection;
if (isSingleFragSelection && !usePlaceholder) {
syncedSelection = TextSelection(
baseOffset: cursor.anchorOffset.clamp(0, syncedText.length),
extentOffset: cursor.focusOffset.clamp(0, syncedText.length),
);
} else if (isMultiFragSelection && !usePlaceholder) {
syncedSelection = TextSelection(
baseOffset: 0,
extentOffset: syncedText.length,
);
} else {
syncedSelection = TextSelection.collapsed(offset: syncedOffset);
}
final selectionChanged =
state.prevSelectionKey !=
'${syncedSelection.baseOffset}:${syncedSelection.extentOffset}';
state.prevSelectionKey =
'${syncedSelection.baseOffset}:${syncedSelection.extentOffset}';
final wasUpdatingSelf = state.updatingSelf;
state.updatingSelf = true;
try {
if (kIsWeb && syncedText.length < state.lastSyncedText.length) {
connectionManager.connection!.setEditingState(const TextEditingValue());
}
if (defaultTargetPlatform == TargetPlatform.iOS && selectionChanged) {
connectionManager.connection!.setEditingState(const TextEditingValue());
}
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) {
// On macOS, we need to set the editing state to an empty value to clear the composition
final newValue = TextEditingValue(
text: syncedText,
selection: syncedSelection,
composing: state.isComposing && state.composingRange.isValid
? state.composingRange
: TextRange.empty,
);
final isDifferent =
_currentPlatformValue.text != newValue.text ||
_currentPlatformValue.composing != newValue.composing;
if (isDifferent) {
_currentPlatformValue = newValue; // Update cache!
connectionManager.connection!.setEditingState(newValue);
}
} else {
connectionManager.connection!.setEditingState(
TextEditingValue(
text: syncedText,
selection: syncedSelection,
composing: TextRange.empty,
),
);
state.lastSyncedText = syncedText;
}
} finally {
state.updatingSelf = wasUpdatingSelf;
}
}