TF-2122 Fix highlight and font search result incorrect
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import 'package:core/utils/app_logger.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
extension StringExtension on String {
|
extension StringExtension on String {
|
||||||
|
|
||||||
@@ -39,11 +38,4 @@ extension StringExtension on String {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String get overflow {
|
|
||||||
return characters
|
|
||||||
.replaceAll(Characters(''), Characters('\u{200B}'))
|
|
||||||
.replaceAll(Characters('-'), Characters('\u{2011}'))
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,66 +1,62 @@
|
|||||||
import 'package:core/presentation/utils/style_utils.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class RichTextBuilder {
|
class RichTextBuilder extends StatelessWidget {
|
||||||
|
|
||||||
final String _textOrigin;
|
final String textOrigin;
|
||||||
final String _wordToStyle;
|
final String wordToStyle;
|
||||||
final TextStyle _styleOrigin;
|
final TextStyle styleOrigin;
|
||||||
final TextStyle _styleWord;
|
final TextStyle styleWord;
|
||||||
|
|
||||||
Key? _key;
|
const RichTextBuilder({
|
||||||
int? _maxLines;
|
super.key,
|
||||||
TextOverflow? _overflow;
|
required this.textOrigin,
|
||||||
|
required this.wordToStyle,
|
||||||
|
required this.styleOrigin,
|
||||||
|
required this.styleWord,
|
||||||
|
});
|
||||||
|
|
||||||
RichTextBuilder(
|
@override
|
||||||
this._textOrigin,
|
Widget build(BuildContext context) {
|
||||||
this._wordToStyle,
|
return Text.rich(
|
||||||
this._styleOrigin,
|
TextSpan(
|
||||||
this._styleWord,
|
style: styleOrigin,
|
||||||
);
|
children: _getSpans(
|
||||||
|
text: textOrigin,
|
||||||
void key(Key key) {
|
word: wordToStyle,
|
||||||
_key = key;
|
styleOrigin: styleOrigin,
|
||||||
|
styleWord: styleWord,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
style: styleOrigin,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void maxLines(int maxLines) {
|
List<TextSpan> _getSpans({
|
||||||
_maxLines = maxLines;
|
required String text,
|
||||||
}
|
required String word,
|
||||||
|
required TextStyle styleOrigin,
|
||||||
void setOverflow(TextOverflow textOverflow) {
|
required TextStyle styleWord,
|
||||||
_overflow = textOverflow;
|
}) {
|
||||||
}
|
|
||||||
|
|
||||||
RichText build() {
|
|
||||||
return RichText(
|
|
||||||
key: _key,
|
|
||||||
maxLines: _maxLines ?? 1,
|
|
||||||
softWrap: CommonTextStyle.defaultSoftWrap,
|
|
||||||
overflow: _overflow ?? CommonTextStyle.defaultTextOverFlow,
|
|
||||||
text: TextSpan(
|
|
||||||
style: _styleOrigin,
|
|
||||||
children: _getSpans(_textOrigin, _wordToStyle, _styleWord)));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TextSpan> _getSpans(String text, String matchWord, TextStyle style) {
|
|
||||||
List<TextSpan> spans = [];
|
List<TextSpan> spans = [];
|
||||||
int spanBoundary = 0;
|
int spanBoundary = 0;
|
||||||
do {
|
do {
|
||||||
// look for the next match
|
// look for the next match
|
||||||
final startIndex = text.toLowerCase().indexOf(matchWord.toLowerCase(), spanBoundary);
|
final startIndex = text.toLowerCase().indexOf(word.toLowerCase(), spanBoundary);
|
||||||
// if no more matches then add the rest of the string without style
|
// if no more matches then add the rest of the string without style
|
||||||
if (startIndex == -1) {
|
if (startIndex == -1) {
|
||||||
spans.add(TextSpan(text: text.substring(spanBoundary)));
|
spans.add(TextSpan(text: text.substring(spanBoundary), style: styleOrigin));
|
||||||
return spans;
|
return spans;
|
||||||
}
|
}
|
||||||
// add any unStyled text before the next match
|
// add any unStyled text before the next match
|
||||||
if (startIndex > spanBoundary) {
|
if (startIndex > spanBoundary) {
|
||||||
spans.add(TextSpan(text: text.substring(spanBoundary, startIndex)));
|
spans.add(TextSpan(text: text.substring(spanBoundary, startIndex), style: styleOrigin));
|
||||||
}
|
}
|
||||||
// style the matched text
|
// style the matched text
|
||||||
final endIndex = startIndex + matchWord.length;
|
final endIndex = startIndex + word.length;
|
||||||
final spanText = text.substring(startIndex, endIndex);
|
final spanText = text.substring(startIndex, endIndex);
|
||||||
spans.add(TextSpan(text: spanText, style: style));
|
spans.add(TextSpan(text: spanText, style: styleWord));
|
||||||
// mark the boundary to start the next search from
|
// mark the boundary to start the next search from
|
||||||
spanBoundary = endIndex;
|
spanBoundary = endIndex;
|
||||||
// continue until there are no more matches
|
// continue until there are no more matches
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
|
|
||||||
import 'package:core/presentation/extensions/string_extension.dart';
|
|
||||||
import 'package:core/presentation/utils/style_utils.dart';
|
|
||||||
import 'package:core/utils/direction_utils.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class TextOverflowBuilder extends StatelessWidget {
|
class TextOverflowBuilder extends StatelessWidget {
|
||||||
@@ -14,22 +11,23 @@ class TextOverflowBuilder extends StatelessWidget {
|
|||||||
final TextDirection? textDirection;
|
final TextDirection? textDirection;
|
||||||
final TextOverflow? overflow;
|
final TextOverflow? overflow;
|
||||||
|
|
||||||
const TextOverflowBuilder(this.data, {
|
const TextOverflowBuilder(
|
||||||
super.key,
|
this.data,
|
||||||
this.style,
|
{
|
||||||
this.textAlign,
|
super.key,
|
||||||
this.softWrap = CommonTextStyle.defaultSoftWrap,
|
this.style,
|
||||||
this.maxLines = 1,
|
this.textAlign,
|
||||||
this.textDirection,
|
this.softWrap = true,
|
||||||
this.overflow = CommonTextStyle.defaultTextOverFlow,
|
this.maxLines = 1,
|
||||||
});
|
this.textDirection,
|
||||||
|
this.overflow = TextOverflow.ellipsis,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Text(
|
return Text(
|
||||||
DirectionUtils.isDirectionRTLByLanguage(context)
|
data,
|
||||||
? data
|
|
||||||
: data.overflow,
|
|
||||||
style: style,
|
style: style,
|
||||||
textAlign: textAlign,
|
textAlign: textAlign,
|
||||||
softWrap: softWrap,
|
softWrap: softWrap,
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
|
|
||||||
import 'package:core/presentation/extensions/color_extension.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
import 'package:core/presentation/extensions/string_extension.dart';
|
|
||||||
import 'package:core/presentation/resources/image_paths.dart';
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||||
import 'package:core/presentation/utils/style_utils.dart';
|
import 'package:core/presentation/utils/style_utils.dart';
|
||||||
import 'package:core/presentation/views/text/rich_text_builder.dart';
|
import 'package:core/presentation/views/text/rich_text_builder.dart';
|
||||||
import 'package:core/presentation/views/text/text_overflow_builder.dart';
|
import 'package:core/presentation/views/text/text_overflow_builder.dart';
|
||||||
import 'package:core/utils/direction_utils.dart';
|
|
||||||
import 'package:core/utils/platform_info.dart';
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
@@ -88,20 +86,20 @@ mixin BaseEmailItemTile {
|
|||||||
) {
|
) {
|
||||||
if (isSearchEnabled(isSearchEmailRunning, query)) {
|
if (isSearchEnabled(isSearchEmailRunning, query)) {
|
||||||
return RichTextBuilder(
|
return RichTextBuilder(
|
||||||
DirectionUtils.isDirectionRTLByLanguage(context)
|
textOrigin: informationSender(email, mailbox),
|
||||||
? informationSender(email, mailbox)
|
wordToStyle: query?.value ?? '',
|
||||||
: informationSender(email, mailbox).overflow,
|
styleOrigin: TextStyle(
|
||||||
query?.value ?? '',
|
fontSize: 15,
|
||||||
TextStyle(
|
color: buildTextColorForReadEmail(email),
|
||||||
fontSize: 15,
|
fontWeight: buildFontForReadEmail(email)
|
||||||
color: buildTextColorForReadEmail(email),
|
),
|
||||||
fontWeight: buildFontForReadEmail(email)),
|
styleWord: TextStyle(
|
||||||
TextStyle(
|
fontSize: 15,
|
||||||
fontSize: 15,
|
color: buildTextColorForReadEmail(email),
|
||||||
color: buildTextColorForReadEmail(email),
|
backgroundColor: AppColor.bgWordSearch,
|
||||||
backgroundColor: AppColor.bgWordSearch,
|
fontWeight: buildFontForReadEmail(email)
|
||||||
fontWeight: buildFontForReadEmail(email))
|
)
|
||||||
).build();
|
);
|
||||||
} else {
|
} else {
|
||||||
return TextOverflowBuilder(
|
return TextOverflowBuilder(
|
||||||
informationSender(email, mailbox),
|
informationSender(email, mailbox),
|
||||||
@@ -122,20 +120,20 @@ mixin BaseEmailItemTile {
|
|||||||
) {
|
) {
|
||||||
if (isSearchEnabled(isSearchEmailRunning, query)) {
|
if (isSearchEnabled(isSearchEmailRunning, query)) {
|
||||||
return RichTextBuilder(
|
return RichTextBuilder(
|
||||||
DirectionUtils.isDirectionRTLByLanguage(context)
|
textOrigin: email.getEmailTitle(),
|
||||||
? email.getEmailTitle()
|
wordToStyle: query?.value ?? '',
|
||||||
: email.getEmailTitle().overflow,
|
styleOrigin: TextStyle(
|
||||||
query?.value ?? '',
|
fontSize: 13,
|
||||||
TextStyle(
|
color: buildTextColorForReadEmail(email),
|
||||||
fontSize: 13,
|
fontWeight: buildFontForReadEmail(email)
|
||||||
color: buildTextColorForReadEmail(email),
|
),
|
||||||
fontWeight: buildFontForReadEmail(email)),
|
styleWord: TextStyle(
|
||||||
TextStyle(
|
fontSize: 13,
|
||||||
fontSize: 13,
|
backgroundColor: AppColor.bgWordSearch,
|
||||||
backgroundColor: AppColor.bgWordSearch,
|
color: buildTextColorForReadEmail(email),
|
||||||
color: buildTextColorForReadEmail(email),
|
fontWeight: buildFontForReadEmail(email)
|
||||||
fontWeight: buildFontForReadEmail(email))
|
)
|
||||||
).build();
|
);
|
||||||
} else {
|
} else {
|
||||||
return TextOverflowBuilder(
|
return TextOverflowBuilder(
|
||||||
email.getEmailTitle(),
|
email.getEmailTitle(),
|
||||||
@@ -155,19 +153,19 @@ mixin BaseEmailItemTile {
|
|||||||
) {
|
) {
|
||||||
if (isSearchEnabled(isSearchEmailRunning, query)) {
|
if (isSearchEnabled(isSearchEmailRunning, query)) {
|
||||||
return RichTextBuilder(
|
return RichTextBuilder(
|
||||||
DirectionUtils.isDirectionRTLByLanguage(context)
|
textOrigin: email.getPartialContent(),
|
||||||
? email.getPartialContent()
|
wordToStyle: query?.value ?? '',
|
||||||
: email.getPartialContent().overflow,
|
styleOrigin: const TextStyle(
|
||||||
query?.value ?? '',
|
fontSize: 13,
|
||||||
const TextStyle(
|
color: AppColor.colorContentEmail,
|
||||||
fontSize: 13,
|
fontWeight: FontWeight.normal
|
||||||
color: AppColor.colorContentEmail,
|
),
|
||||||
fontWeight: FontWeight.normal),
|
styleWord: const TextStyle(
|
||||||
const TextStyle(
|
fontSize: 13,
|
||||||
fontSize: 13,
|
color: AppColor.colorContentEmail,
|
||||||
color: AppColor.colorContentEmail,
|
backgroundColor: AppColor.bgWordSearch
|
||||||
backgroundColor: AppColor.bgWordSearch)
|
)
|
||||||
).build();
|
);
|
||||||
} else {
|
} else {
|
||||||
return TextOverflowBuilder(
|
return TextOverflowBuilder(
|
||||||
email.getPartialContent(),
|
email.getPartialContent(),
|
||||||
|
|||||||
Reference in New Issue
Block a user