onTextChanged method

void onTextChanged(
  1. String newText,
  2. BuildContext context
)

Implementation

void onTextChanged(String newText, BuildContext context) {
  String oldText = lastChangedText;
  // 检测删除操作
  if (newText.length < oldText.length) {
    int diffIndex = 0;
    while (diffIndex < newText.length &&
        diffIndex < oldText.length &&
        newText[diffIndex] == oldText[diffIndex]) {
      diffIndex++;
    }
    // 修改正则,匹配 "@姓名 ",支持中文、字母、数字与下划线
    RegExp mentionRegExp = RegExp(r'@[\w\u4e00-\u9fa5]+ ');
    for (var m in mentionRegExp.allMatches(oldText)) {
      if (diffIndex >= m.start && diffIndex < m.end) {
        // 计算新的结束索引,避免越界
        int endIndex = m.end > newText.length ? newText.length : m.end;
        newText = newText.substring(0, m.start) + newText.substring(endIndex);
        controller.value = controller.value.copyWith(
            text: newText,
            selection: TextSelection.collapsed(offset: m.start));
        String mentionName = oldText.substring(m.start, m.end);
        removeUserAtInfo(mentionName);
        break;
      }
    }
  }

  RCKChatProvider chatProvider = context.read<RCKChatProvider>();
  if (newText.isEmpty) {
    chatProvider.clearDraft();
  } else {
    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();
      Navigator.pushNamed(context, '/at_people',
              arguments: {'groupId': chatProvider.conversation.targetId})
          .then((value) {
        RCKUserAtInfo? atInfo = value as RCKUserAtInfo?;
        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 newText = currentText.replaceRange(
            cursorIndex,
            cursorIndex,
            '${atInfo.name} ',
          );
          controller.value = controller.value.copyWith(
            text: newText,
            selection: TextSelection.collapsed(
              offset: cursorIndex + atInfo.name.length + 1,
            ),
          );
        }
        addUserAtInfo(atInfo.userId);
        if (context.mounted) {
          onTextChanged(controller.text, context);
        }
      });
    }
  }
  lastChangedText = newText;
}