Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: combine token with following punctuation to prevent punctuation … #1783

Merged
merged 1 commit into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions lib/pangea/events/utils/message_text_util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,44 +25,68 @@ 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;

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) &&
!hideContent &&
!hasHiddenContent,
),
);

globalIndex = endIndex;
pointer = nextTokenPointer;
continue;
}

return tokenPositions;
Expand Down
72 changes: 58 additions & 14 deletions lib/pangea/toolbar/widgets/message_token_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,27 @@ 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;

const TokenPosition({
required this.start,
required this.end,
required this.tokenStart,
required this.tokenEnd,
required this.hideContent,
required this.selected,
this.token,
Expand Down Expand Up @@ -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,
Expand All @@ -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(),
),
],
),
),
),
Expand Down
Loading