import '../../../../api/marianumcloud/talk/chat/get_chat_response.dart'; import '../../../../api/marianumcloud/talk/chat/rich_object_string_processor.dart'; import '../../../../api/marianumcloud/talk/room/get_room_response.dart'; class ChatSearchMatch { final int messageId; final int timestamp; const ChatSearchMatch({required this.messageId, required this.timestamp}); } class ChatSearchController { /// System messages that are folded into other bubbles (reactions, poll /// votes, deletions) and therefore never rendered nor searched as their own /// entry. static bool isHiddenSystemMessage(GetChatResponseObject element) => element.systemMessage.contains('reaction') || element.systemMessage.contains('poll_voted') || element.systemMessage.contains('message_deleted'); static List findMatches( GetChatResponse response, String query, ) { final q = query.trim().toLowerCase(); if (q.isEmpty) return const []; final matches = []; for (final element in response.sortByTimestamp()) { if (isHiddenSystemMessage(element)) continue; final haystackText = RichObjectStringProcessor.parseToString( element.message, element.messageParameters, ).toLowerCase(); var matched = haystackText.contains(q); if (!matched && element.messageType != GetRoomResponseObjectMessageType.system) { matched = element.actorDisplayName.toLowerCase().contains(q); } if (matched) { matches.add( ChatSearchMatch( messageId: element.id, timestamp: element.timestamp, ), ); } } matches.sort((a, b) => b.timestamp.compareTo(a.timestamp)); return matches; } }