Documentation Index
Fetch the complete documentation index at: https://cometchat-22654f5b-docs-android-v6-beta2.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Introduction
TheShortcutFormatter class extends CometChatTextFormatter to handle shortcuts within messages. This guide walks you through implementing shortcut extensions in your CometChat V6 application.
Setup
- Create the ShortcutFormatter class by extending
CometChatTextFormatter:
- Dart
import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
class ShortcutFormatter extends CometChatTextFormatter {
@override
void init() {
trackingCharacter ??= "!";
}
bool isShortcutTracking = false;
void prepareShortcuts(TextEditingController textEditingController) {
CometChat.callExtension('message-shortcuts', 'GET', '/v1/fetch', null,
onSuccess: (map) {
if (map.isNotEmpty) {
Map<String, dynamic> data = map["data"];
if (data.isNotEmpty) {
Map<String, dynamic> shortcuts = data["shortcuts"];
if (shortcuts.isNotEmpty) {
parseData(shortcuts: shortcuts, textEditingController: textEditingController);
}
}
}
},
onError: (error) {},
);
}
void parseData({Map<String, dynamic>? shortcuts, required TextEditingController textEditingController}) async {
if (shortcuts == null || shortcuts.isEmpty) {
suggestionListEventSink?.add([]);
if (onSearch != null) onSearch!(null);
CometChatUIEvents.hidePanel(composerId, CustomUIPosition.composerPreview);
} else {
CometChatUIEvents.hidePanel(composerId, CustomUIPosition.composerPreview);
if (suggestionListEventSink != null && shortcuts.isNotEmpty) {
List<SuggestionListItem> list = [];
shortcuts.forEach((key, value) => list.add(SuggestionListItem(
id: key,
title: "$key → $value",
onTap: () {
int cursorPos = textEditingController.selection.base.offset;
String left = textEditingController.text.substring(0, cursorPos - 1);
String right = textEditingController.text.substring(cursorPos);
textEditingController.text = "$left$value $right";
updatePreviousText(textEditingController.text);
textEditingController.selection = TextSelection(
baseOffset: cursorPos - 1 + "$value".length + 1,
extentOffset: cursorPos - 1 + "$value".length + 1,
);
resetMatchTracker();
isShortcutTracking = false;
CometChatUIEvents.hidePanel(composerId, CustomUIPosition.composerPreview);
},
)));
suggestionListEventSink?.add(list);
}
}
}
void updatePreviousText(String text) {
previousTextEventSink?.add(text);
}
void resetMatchTracker() {
suggestionListEventSink?.add([]);
if (onSearch != null) onSearch!(null);
}
@override
void onChange(TextEditingController textEditingController, String previousText) {
var cursorPosition = textEditingController.selection.base.offset;
if (textEditingController.text.isEmpty) {
resetMatchTracker();
return;
}
// Handle shortcut tracking logic
String previousCharacter = cursorPosition == 0 ? "" : textEditingController.text[cursorPosition - 1];
bool isSpace = cursorPosition == 1 || (textEditingController.text.length > 1 && cursorPosition > 1 &&
(textEditingController.text[cursorPosition - 2] == " " || textEditingController.text[cursorPosition - 2] == "\n"));
if (isShortcutTracking) {
isShortcutTracking = false;
if (onSearch != null) onSearch!(null);
CometChatUIEvents.hidePanel(composerId, CustomUIPosition.composerPreview);
} else if (previousCharacter == trackingCharacter && isSpace) {
isShortcutTracking = true;
if (onSearch != null) onSearch!(trackingCharacter);
CometChatUIEvents.showPanel(composerId, CustomUIPosition.composerPreview,
(context) => getLoadingIndicator(context, cometChatTheme));
prepareShortcuts(textEditingController);
}
}
@override
TextStyle getMessageInputTextStyle(CometChatTheme theme) {
throw UnimplementedError();
}
@override
void handlePreMessageSend(BuildContext context, BaseMessage baseMessage) {}
@override
void onScrollToBottom(TextEditingController textEditingController) {}
}
Usage
Pass theShortcutFormatter to the textFormatters property of CometChatMessageComposer:
- Dart
CometChatMessageComposer(
user: user,
textFormatters: [ShortcutFormatter()],
)