fix: combine token with following punctuation to prevent punctuation from causing newline (#1783)

pull/1688/head
ggurdin 9 months ago committed by GitHub
parent cd0650f6b7
commit 4fe67a9384
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -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…
Cancel
Save