diff --git a/lib/src/annotation_editing_controller.dart b/lib/src/annotation_editing_controller.dart index 7df935b..cf95544 100644 --- a/lib/src/annotation_editing_controller.dart +++ b/lib/src/annotation_editing_controller.dart @@ -8,9 +8,16 @@ class AnnotationEditingController extends TextEditingController { // Generate the Regex pattern for matching all the suggestions in one. AnnotationEditingController(this._mapping) - : _pattern = _mapping.keys.isNotEmpty - ? "(${_mapping.keys.map((key) => RegExp.escape(key)).join('|')})" - : null; + { + _pattern = null; + + if(_mapping.keys.isNotEmpty){ + var result = _mapping.keys.map((key) => RegExp.escape(key)).toList(); + result.sort((b,a) => a.toLowerCase().compareTo(b.toLowerCase())); + var finalresult = result.join('|'); + _pattern = finalresult; + } + } /// Can be used to get the markup from the controller directly. String get markupText { @@ -51,7 +58,11 @@ class AnnotationEditingController extends TextEditingController { set mapping(Map _mapping) { this._mapping = _mapping; - _pattern = "(${_mapping.keys.map((key) => RegExp.escape(key)).join('|')})"; + var result = _mapping.keys.map((key) => RegExp.escape(key)).toList(); + result.sort((b,a) => a.toLowerCase().compareTo(b.toLowerCase())); + var finalresult = result.join('|'); + _pattern = finalresult; + } @override diff --git a/lib/src/mention_view.dart b/lib/src/mention_view.dart index ec8be89..f5a2017 100644 --- a/lib/src/mention_view.dart +++ b/lib/src/mention_view.dart @@ -327,8 +327,59 @@ class FlutterMentionsState extends State { final lengthMap = []; - // split on each word and generate a list with start & end position of each word. - controller!.value.text.split(RegExp(r'(\s)')).forEach((element) { + List textList = controller!.value.text.split(RegExp(r'(\s)')); + + _pattern = widget.mentions.map((e) => e.trigger).join('|'); + + var mentionIndex = -2; + + List triggerList = widget.mentions.map((e) => e.trigger).toList(); + + triggerList.forEach((element) { + var triggerIndex = textList.lastIndexWhere((e) => e.contains(element)); + if (triggerIndex > mentionIndex) { + mentionIndex = triggerIndex; + } + }); + + if (textList.length - 1 > mentionIndex && mentionIndex != -1) { + var nextWordIndex = mentionIndex + 1; + + var mention = textList[mentionIndex] + ' ' + textList[nextWordIndex]; + + _pattern = widget.mentions.map((e) => e.trigger).join('|'); + + // Filter the list based on the latest entered mention + final list = + widget.mentions.firstWhere((e) => mention.contains(e.trigger)).data; + + // Loop until the the mention is contain in given mention list or not + while (list.indexWhere((element) { + final displayName = element['display'].toLowerCase(); + return displayName == mention.substring(1).toLowerCase() || + displayName.contains(mention.substring(1).toLowerCase()); + }) != + -1) { + // Assign full name mention to the list if the mention is is exist in the list + textList[mentionIndex] = mention; + + // Assign null to the next word because it's already concatenate to the mention index word + textList[nextWordIndex] = "null"; + + // If the word is exist on the next index then concatenate it otherwise break the loop + if (textList.length - 1 > nextWordIndex) { + // concatenate the next word to the mention and again iterate the while loop with condition of check weather the mention is available or in the list or not + mention = mention + ' ' + textList[++nextWordIndex]; + } else { + break; + } + } + } + + // Remove all the null entries from the list + textList.removeWhere((element) => element == "null"); + + textList.forEach((element) { lengthMap.add( LengthMap(str: element, start: _pos, end: _pos + element.length)); @@ -380,6 +431,8 @@ class FlutterMentionsState extends State { controller!.text = widget.defaultText!; } + _pattern = widget.mentions.map((e) => e.trigger).join('|'); + // setup a listener to figure out which suggestions to show based on the trigger controller!.addListener(suggestionListerner);