Skip to content

Commit

Permalink
krille-chan#39 Highlight search term in citations
Browse files Browse the repository at this point in the history
  • Loading branch information
carowebtec authored and Matthias committed Mar 6, 2023
1 parent 36ef733 commit 507f25e
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 42 deletions.
9 changes: 6 additions & 3 deletions lib/pages/chat/events/message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,12 @@ class Message extends StatelessWidget {
margin: EdgeInsets.symmetric(
vertical: 4.0 *
AppConfig.bubbleSizeFactor),
child: ReplyContent(replyEvent,
ownMessage: ownMessage,
timeline: timeline),
child: ReplyContent(
replyEvent,
ownMessage: ownMessage,
timeline: timeline,
searchTerm: searchTerm,
),
),
),
);
Expand Down
33 changes: 4 additions & 29 deletions lib/pages/chat/events/message_content.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:matrix/matrix.dart';
import 'package:matrix_link_text/link_text.dart';

import 'package:fluffychat/pages/chat/events/video_player.dart';
import 'package:fluffychat/pages/chat_search/search_result_formatter.dart';
import 'package:fluffychat/utils/date_time_extension.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_locals.dart';
import 'package:fluffychat/widgets/avatar.dart';
Expand Down Expand Up @@ -90,35 +91,9 @@ class MessageContent extends StatelessWidget {
);
}

bool _isSearchResult() {
return searchTerm != null && searchTerm!.isNotEmpty;
}

String _getEventTextFormatted() {
var text = event.formattedText;
if (_isSearchResult()) {
// search result messages may not be formatted-messages originally
// -> take normal text in this case
if (text.isEmpty) {
text = event.text;
}

return _replaceSearchResults(text);
} else {
return text;
}
}

String _replaceSearchResults(String text) {
final searchExp = RegExp(searchTerm!, caseSensitive: false);
text = text.replaceAllMapped(
searchExp, (match) => "<b><i>${match[0]}</i></b>");

return text;
}

@override
Widget build(BuildContext context) {
final textFormatter = SearchResultFormatter(searchTerm);
final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor;
final buttonTextColor =
event.senderId == Matrix.of(context).client.userID ? textColor : null;
Expand Down Expand Up @@ -160,8 +135,8 @@ class MessageContent extends StatelessWidget {
case MessageTypes.Emote:
if (AppConfig.renderHtml &&
!event.redacted &&
(event.isRichMessage || _isSearchResult())) {
String html = _getEventTextFormatted();
(event.isRichMessage || textFormatter.isSearchResult())) {
String html = textFormatter.getEventTextFormatted(event);
if (event.messageType == MessageTypes.Emote) {
html = '* $html';
}
Expand Down
22 changes: 12 additions & 10 deletions lib/pages/chat/events/reply_content.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@ import 'package:matrix/matrix.dart';

import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_locals.dart';
import '../../../config/app_config.dart';
import '../../chat_search/search_result_formatter.dart';
import 'html_message.dart';

class ReplyContent extends StatelessWidget {
final Event replyEvent;
final bool ownMessage;
final Timeline? timeline;
final String? searchTerm;

const ReplyContent(
this.replyEvent, {
this.ownMessage = false,
Key? key,
this.timeline,
}) : super(key: key);
const ReplyContent(this.replyEvent,
{this.ownMessage = false, Key? key, this.timeline, this.searchTerm})
: super(key: key);

@override
Widget build(BuildContext context) {
Widget replyBody;
final timeline = this.timeline;
final textFormatter = SearchResultFormatter(searchTerm);
final displayEvent =
timeline != null ? replyEvent.getDisplayEvent(timeline) : replyEvent;
final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor;
Expand All @@ -32,14 +32,16 @@ class ReplyContent extends StatelessWidget {
[MessageTypes.Text, MessageTypes.Notice, MessageTypes.Emote]
.contains(displayEvent.messageType) &&
!displayEvent.redacted &&
displayEvent.content['format'] == 'org.matrix.custom.html' &&
displayEvent.content['formatted_body'] is String) {
String? html = displayEvent.content['formatted_body'];
(displayEvent.content['format'] == 'org.matrix.custom.html' &&
displayEvent.content['formatted_body'] is String ||
textFormatter.isSearchResult())) {
String html = textFormatter.getEventTextFormatted(displayEvent);

if (displayEvent.messageType == MessageTypes.Emote) {
html = '* $html';
}
replyBody = HtmlMessage(
html: html!,
html: html,
defaultTextStyle: TextStyle(
color: ownMessage
? Theme.of(context).colorScheme.onPrimary
Expand Down
54 changes: 54 additions & 0 deletions lib/pages/chat_search/search_result_formatter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import 'package:matrix/matrix.dart';

class SearchResultFormatter {
String? _searchTerm = "";
RegExp? _searchExp;

SearchResultFormatter(String? searchTerm) {
_searchTerm = searchTerm;
if (isSearchResult()) {
_searchExp = RegExp(searchTerm!, caseSensitive: false);
}
}

bool isSearchResult() {
return _searchTerm != null && _searchTerm!.isNotEmpty;
}

String getEventTextFormatted(Event event) {
var text = event.formattedText;
if (isSearchResult()) {
// search result messages may not be a formatted-messages originally
// -> take normal text in this case
if (text.isEmpty) {
text = event.text;
}

return _replaceSearchResults(text);
} else {
return text;
}
}

String _replaceSearchResults(String text) {
// final startIndex = _getStartIndex(text);
text = text.replaceAllMapped(
_searchExp!, (match) => "<b><i>${match[0]}</i></b>");

return text;
}

/*int _getStartIndex(String text) {
const replyEndText = "</mx-reply>";
final replyIndex = text.indexOf(replyEndText);
if(replyIndex < 0) {
return 0;
}
else {
// if text contains a replay start after reply
return replyIndex+replyEndText.length;
}
}
*/
}

0 comments on commit 507f25e

Please sign in to comment.