fix: combine token with following punctuation to prevent punctuation from causing newline (#1783)
This commit is contained in:
parent
cd0650f6b7
commit
4fe67a9384
2 changed files with 85 additions and 17 deletions
|
|
@ -25,14 +25,16 @@ class MessageTextUtil {
|
|||
final List<TokenPosition> tokenPositions = [];
|
||||
int globalIndex = 0;
|
||||
|
||||
for (final token
|
||||
in pangeaMessageEvent.messageDisplayRepresentation!.tokens!) {
|
||||
final tokens = pangeaMessageEvent.messageDisplayRepresentation!.tokens!;
|
||||
int pointer = 0;
|
||||
while (pointer < tokens.length) {
|
||||
final token = tokens[pointer];
|
||||
final start = token.start;
|
||||
final end = token.end;
|
||||
|
||||
// Calculate the number of grapheme clusters up to the start and end positions
|
||||
final int startIndex = messageCharacters.take(start).length;
|
||||
final int endIndex = messageCharacters.take(end).length;
|
||||
int endIndex = messageCharacters.take(end).length;
|
||||
|
||||
final hideContent =
|
||||
messageAnalyticsEntry?.isTokenInHiddenWordActivity(token) ?? false;
|
||||
|
|
@ -40,21 +42,40 @@ class MessageTextUtil {
|
|||
final hasHiddenContent =
|
||||
messageAnalyticsEntry?.hasHiddenWordActivity ?? false;
|
||||
|
||||
// if this is white space, add position without token
|
||||
if (globalIndex < startIndex) {
|
||||
tokenPositions.add(
|
||||
TokenPosition(
|
||||
start: globalIndex,
|
||||
end: startIndex,
|
||||
tokenStart: globalIndex,
|
||||
tokenEnd: startIndex,
|
||||
hideContent: false,
|
||||
selected: (isSelected?.call(token) ?? false) && !hasHiddenContent,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// group tokens with punctuation next to it so punctuation doesn't cause newline
|
||||
final List<PangeaToken> followingPunctTokens = [];
|
||||
int nextTokenPointer = pointer + 1;
|
||||
while (nextTokenPointer < tokens.length) {
|
||||
final nextToken = tokens[nextTokenPointer];
|
||||
if (nextToken.pos == 'PUNCT') {
|
||||
followingPunctTokens.add(nextToken);
|
||||
nextTokenPointer++;
|
||||
endIndex = messageCharacters.take(nextToken.end).length;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
tokenPositions.add(
|
||||
TokenPosition(
|
||||
start: startIndex,
|
||||
end: endIndex,
|
||||
tokenStart: startIndex,
|
||||
tokenEnd: messageCharacters.take(end).length,
|
||||
token: token,
|
||||
hideContent: hideContent,
|
||||
selected: (isSelected?.call(token) ?? false) &&
|
||||
|
|
@ -62,7 +83,10 @@ class MessageTextUtil {
|
|||
!hasHiddenContent,
|
||||
),
|
||||
);
|
||||
|
||||
globalIndex = endIndex;
|
||||
pointer = nextTokenPointer;
|
||||
continue;
|
||||
}
|
||||
|
||||
return tokenPositions;
|
||||
|
|
|
|||
|
|
@ -70,8 +70,18 @@ class MessageTokenText extends StatelessWidget {
|
|||
}
|
||||
|
||||
class TokenPosition {
|
||||
/// Start index of the full substring in the message
|
||||
final int start;
|
||||
|
||||
/// End index of the full substring in the message
|
||||
final int end;
|
||||
|
||||
/// Start index of the token in the message
|
||||
final int tokenStart;
|
||||
|
||||
/// End index of the token in the message
|
||||
final int tokenEnd;
|
||||
|
||||
final bool selected;
|
||||
final bool hideContent;
|
||||
final PangeaToken? token;
|
||||
|
|
@ -79,6 +89,8 @@ class TokenPosition {
|
|||
const TokenPosition({
|
||||
required this.start,
|
||||
required this.end,
|
||||
required this.tokenStart,
|
||||
required this.tokenEnd,
|
||||
required this.hideContent,
|
||||
required this.selected,
|
||||
this.token,
|
||||
|
|
@ -225,6 +237,19 @@ class MessageTextWidget extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
// if the tokenPosition is a combination of the token and following punctuation
|
||||
// split them so that only the token itself is highlighted when clicked
|
||||
String firstSubstring = substring;
|
||||
String secondSubstring = '';
|
||||
|
||||
if (tokenPosition.end != tokenPosition.tokenEnd) {
|
||||
final splitIndex = (tokenPosition.end - tokenPosition.start) -
|
||||
(tokenPosition.end - tokenPosition.tokenEnd);
|
||||
firstSubstring = substring.substring(0, splitIndex);
|
||||
secondSubstring = substring.substring(splitIndex);
|
||||
}
|
||||
|
||||
return WidgetSpan(
|
||||
child: MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
|
|
@ -233,21 +258,40 @@ class MessageTextWidget extends StatelessWidget {
|
|||
? () => onClick?.call(tokenPosition)
|
||||
: null,
|
||||
child: RichText(
|
||||
text: LinkifySpan(
|
||||
text: substring,
|
||||
style: style.merge(
|
||||
TextStyle(
|
||||
backgroundColor: backgroundColor,
|
||||
text: TextSpan(
|
||||
children: [
|
||||
LinkifySpan(
|
||||
text: firstSubstring,
|
||||
style: style.merge(
|
||||
TextStyle(
|
||||
backgroundColor: backgroundColor,
|
||||
),
|
||||
),
|
||||
linkStyle: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
color:
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.onPrimary,
|
||||
),
|
||||
onOpen: (url) =>
|
||||
UrlLauncher(context, url.url).launchUrl(),
|
||||
),
|
||||
),
|
||||
linkStyle: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
color: Theme.of(context).brightness == Brightness.light
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.onPrimary,
|
||||
),
|
||||
onOpen: (url) =>
|
||||
UrlLauncher(context, url.url).launchUrl(),
|
||||
if (secondSubstring.isNotEmpty)
|
||||
LinkifySpan(
|
||||
text: secondSubstring,
|
||||
style: style,
|
||||
linkStyle: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
color: Theme.of(context).brightness ==
|
||||
Brightness.light
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.onPrimary,
|
||||
),
|
||||
onOpen: (url) =>
|
||||
UrlLauncher(context, url.url).launchUrl(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue