onTextChanged method
Implementation
void onTextChanged(String newText, BuildContext context) {
String oldText = lastChangedText;
newText = _syncMentionsWithText(oldText, newText);
RCKChatProvider chatProvider = context.read<RCKChatProvider>();
if (isEditing) {
_scheduleEditedDraft(chatProvider, newText);
if (newText.isEmpty) {
unawaited(chatProvider.clearDraft());
} else {
unawaited(chatProvider.saveDraft(newText));
}
} else if (newText.isEmpty) {
unawaited(chatProvider.clearDraft());
} else {
unawaited(chatProvider.saveDraft(newText));
}
// 当文本增加字符且新增加的字符中包含 '@' 时触发
if (newText.length > oldText.length &&
chatProvider.conversation.conversationType ==
RCIMIWConversationType.group) {
int cursorIndex = controller.selection.baseOffset;
// 验证 cursorIndex 的有效性
if (cursorIndex == -1) {
cursorIndex = newText.length;
}
if (cursorIndex > 0 && newText[cursorIndex - 1] == '@') {
context.read<RCKAudioPlayerProvider>().stopVoiceMessage();
context.read<RCKVoiceRecordProvider>().cancelRecord();
// @ 人页返回是跨页面异步回调。记录发起时的编辑、Engine、账号和会话
// 身份,避免期间切换会话或退出编辑后把结果写入另一份草稿。
final atPeopleOperationId = _editOperationId;
final atPeopleEditingMessageUId = _editingMessage?.messageUId;
final atPeopleWasEditing = isEditing;
final atPeopleEngineProvider = chatProvider.engineProvider;
final atPeopleEngine = atPeopleEngineProvider.engine;
final atPeopleUserId = atPeopleEngineProvider.currentUserId;
final atPeopleConversationType =
chatProvider.conversation.conversationType;
final atPeopleTargetId = chatProvider.conversation.targetId;
final atPeopleChannelId = chatProvider.conversation.channelId;
Navigator.pushNamed(
context,
'/at_people',
arguments: {'groupId': chatProvider.conversation.targetId},
).then((value) {
if (!context.mounted) return;
if (!_isAtPeopleRequestCurrent(
context,
chatProvider,
operationId: atPeopleOperationId,
editingMessageUId: atPeopleEditingMessageUId,
wasEditing: atPeopleWasEditing,
engineProvider: atPeopleEngineProvider,
engine: atPeopleEngine,
userId: atPeopleUserId,
conversationType: atPeopleConversationType,
targetId: atPeopleTargetId,
channelId: atPeopleChannelId,
)) {
return;
}
final atInfo = value is RCKUserAtInfo ? value : null;
if (atInfo == null) return;
final currentText = controller.text;
final selection = controller.selection;
int cursorIndex = selection.baseOffset;
// 验证 cursorIndex 的有效性
if (cursorIndex == -1) {
cursorIndex = currentText.length;
}
// 判断光标前一个字符是否为 '@'
if (cursorIndex > 0 && currentText[cursorIndex - 1] == '@') {
final insertedText = '${atInfo.name} ';
final newText = currentText.replaceRange(
cursorIndex,
cursorIndex,
insertedText,
);
if (!atPeopleWasEditing &&
newText.length > kMessageInputMaxLength) {
return;
}
controller.value = controller.value.copyWith(
text: newText,
selection: TextSelection.collapsed(
offset: cursorIndex + insertedText.length,
),
);
if (!context.mounted || _disposed) return;
onTextChanged(controller.text, context);
final mentionStart = cursorIndex - 1;
final mentionText = '@${atInfo.name} ';
if (mentionStart >= 0 &&
mentionStart + mentionText.length <= controller.text.length &&
controller.text.substring(
mentionStart,
mentionStart + mentionText.length,
) ==
mentionText) {
_registerMention(
RCKMessageEditMention(
userId: atInfo.userId,
text: mentionText,
start: mentionStart,
end: mentionStart + mentionText.length,
),
);
}
}
});
}
}
lastChangedText = newText;
}