remove unused files
This commit is contained in:
parent
51490605fb
commit
524b8978f5
4 changed files with 10 additions and 633 deletions
|
|
@ -166,28 +166,23 @@ class HtmlMessage extends StatelessWidget {
|
|||
(token) => token.text.offset == offset && token.text.length == length,
|
||||
);
|
||||
|
||||
/// Wrap token spans in token tags so styling / functions can be applied
|
||||
dom.Node _tokenizeHtml(
|
||||
dom.Node element,
|
||||
String fullHtml,
|
||||
List<PangeaToken> remainingTokens,
|
||||
) {
|
||||
String _addTokenTags() {
|
||||
final regex = RegExp(r'(<[^>]+>)');
|
||||
|
||||
final matches = regex.allMatches(fullHtml);
|
||||
final matches = regex.allMatches(html);
|
||||
final List<String> result = <String>[];
|
||||
int lastEnd = 0;
|
||||
|
||||
for (final match in matches) {
|
||||
if (match.start > lastEnd) {
|
||||
result.add(fullHtml.substring(lastEnd, match.start)); // Text before tag
|
||||
result.add(html.substring(lastEnd, match.start)); // Text before tag
|
||||
}
|
||||
result.add(match.group(0)!); // The tag itself
|
||||
lastEnd = match.end;
|
||||
}
|
||||
|
||||
if (lastEnd < fullHtml.length) {
|
||||
result.add(fullHtml.substring(lastEnd)); // Remaining text after last tag
|
||||
if (lastEnd < html.length) {
|
||||
result.add(html.substring(lastEnd)); // Remaining text after last tag
|
||||
}
|
||||
|
||||
for (final PangeaToken token in tokens ?? []) {
|
||||
|
|
@ -217,7 +212,7 @@ class HtmlMessage extends StatelessWidget {
|
|||
]);
|
||||
}
|
||||
|
||||
return dom.Element.html('<span>${result.join()}</span>');
|
||||
return result.join();
|
||||
}
|
||||
// Pangea#
|
||||
|
||||
|
|
@ -834,10 +829,7 @@ class HtmlMessage extends StatelessWidget {
|
|||
// maxLines: limitHeight ? 64 : null,Add commentMore actions
|
||||
// overflow: TextOverflow.fade,
|
||||
// );
|
||||
dom.Node parsed = parser.parse(html).body ?? dom.Element.html('');
|
||||
if (tokens != null) {
|
||||
parsed = _tokenizeHtml(parsed, html, List.from(tokens!));
|
||||
}
|
||||
final parsed = parser.parse(_addTokenTags()).body ?? dom.Element.html('');
|
||||
return SelectionArea(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ import 'package:fluffychat/config/app_config.dart';
|
|||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_selection_repo.dart';
|
||||
import 'package:fluffychat/pangea/toolbar/widgets/message_token_text.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import '../../../utils/matrix_sdk_extensions/matrix_locals.dart';
|
||||
|
||||
|
|
@ -88,26 +86,9 @@ class ChatListItemSubtitle extends StatelessWidget {
|
|||
if (snapshot.hasData) {
|
||||
final messageEventAndTokens = snapshot.data as MessageEventAndTokens;
|
||||
final pangeaMessageEvent = messageEventAndTokens.event;
|
||||
final tokens = messageEventAndTokens.tokens;
|
||||
|
||||
final analyticsEntry = tokens != null
|
||||
? PracticeSelectionRepo.get(
|
||||
messageEventAndTokens.event.messageDisplayLangCode,
|
||||
tokens,
|
||||
)
|
||||
: null;
|
||||
|
||||
return MessageTextWidget(
|
||||
pangeaMessageEvent: pangeaMessageEvent,
|
||||
existingStyle: style,
|
||||
messageAnalyticsEntry: analyticsEntry,
|
||||
isSelected: null,
|
||||
onClick: null,
|
||||
softWrap: false,
|
||||
maxLines: pangeaMessageEvent.room.notificationCount >= 1 ? 2 : 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
isMessage: false,
|
||||
textScaler: MediaQuery.textScalerOf(context),
|
||||
return Text(
|
||||
pangeaMessageEvent.messageDisplayText,
|
||||
style: style,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,177 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_selection.dart';
|
||||
|
||||
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 hideContent;
|
||||
final PangeaToken? token;
|
||||
final bool isHighlighted;
|
||||
final bool selected;
|
||||
|
||||
const TokenPosition({
|
||||
required this.start,
|
||||
required this.end,
|
||||
required this.tokenStart,
|
||||
required this.tokenEnd,
|
||||
required this.hideContent,
|
||||
required this.selected,
|
||||
required this.isHighlighted,
|
||||
this.token,
|
||||
});
|
||||
}
|
||||
|
||||
class MessageTextUtil {
|
||||
static final Map<String, List<TokenPosition>> _tokenPositionsCache = {};
|
||||
|
||||
static List<TokenPosition>? getTokenPositions(
|
||||
PangeaMessageEvent pangeaMessageEvent, {
|
||||
PracticeSelection? messageAnalyticsEntry,
|
||||
bool Function(PangeaToken)? isSelected,
|
||||
bool Function(PangeaToken)? isHighlighted,
|
||||
}) {
|
||||
try {
|
||||
if (pangeaMessageEvent.messageDisplayRepresentation?.tokens == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final cacheKey = pangeaMessageEvent.event
|
||||
.getDisplayEvent(pangeaMessageEvent.timeline)
|
||||
.eventId;
|
||||
|
||||
if (_tokenPositionsCache.containsKey(cacheKey)) {
|
||||
return _tokenPositionsCache[cacheKey]!
|
||||
.map(
|
||||
(t) => TokenPosition(
|
||||
start: t.start,
|
||||
end: t.end,
|
||||
tokenStart: t.tokenStart,
|
||||
tokenEnd: t.tokenEnd,
|
||||
hideContent: t.hideContent,
|
||||
selected: t.token != null
|
||||
? isSelected?.call(t.token!) ?? false
|
||||
: false,
|
||||
isHighlighted: t.token != null
|
||||
? isHighlighted?.call(t.token!) ?? false
|
||||
: false,
|
||||
token: t.token,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
// Convert the entire message into a list of characters
|
||||
final Characters messageCharacters =
|
||||
pangeaMessageEvent.messageDisplayText.characters;
|
||||
|
||||
// When building token positions, use grapheme cluster indices
|
||||
final List<TokenPosition> tokenPositions = [];
|
||||
int globalIndex = 0;
|
||||
|
||||
final tokens = pangeaMessageEvent.messageDisplayRepresentation!.tokens!;
|
||||
int pointer = 0;
|
||||
while (pointer < tokens.length) {
|
||||
PangeaToken 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;
|
||||
int endIndex = messageCharacters.take(end).length;
|
||||
|
||||
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,
|
||||
isHighlighted: isHighlighted?.call(token) ?? false,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// group tokens with punctuation before and after so punctuation doesn't cause newline
|
||||
int nextTokenPointer = pointer + 1;
|
||||
while (nextTokenPointer < tokens.length) {
|
||||
final nextToken = tokens[nextTokenPointer];
|
||||
if (token.pos == 'PUNCT' && token.end == nextToken.start) {
|
||||
token = nextToken;
|
||||
nextTokenPointer++;
|
||||
endIndex = messageCharacters.take(nextToken.end).length;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
while (nextTokenPointer < tokens.length) {
|
||||
final nextToken = tokens[nextTokenPointer];
|
||||
|
||||
if (nextToken.pos == 'PUNCT' && token.end == nextToken.start) {
|
||||
nextTokenPointer++;
|
||||
endIndex = messageCharacters.take(nextToken.end).length;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
final hideContent =
|
||||
messageAnalyticsEntry?.isTokenInHiddenWordActivity(token) ?? false;
|
||||
|
||||
tokenPositions.add(
|
||||
TokenPosition(
|
||||
start: startIndex,
|
||||
end: endIndex,
|
||||
tokenStart: messageCharacters.take(token.start).length,
|
||||
tokenEnd: messageCharacters.take(token.end).length,
|
||||
token: token,
|
||||
hideContent: hideContent,
|
||||
selected: (isSelected?.call(token) ?? false) &&
|
||||
!hideContent &&
|
||||
!hasHiddenContent,
|
||||
isHighlighted: isHighlighted?.call(token) ?? false,
|
||||
),
|
||||
);
|
||||
|
||||
globalIndex = endIndex;
|
||||
pointer = nextTokenPointer;
|
||||
continue;
|
||||
}
|
||||
|
||||
_tokenPositionsCache[cacheKey] = tokenPositions;
|
||||
|
||||
return tokenPositions;
|
||||
} catch (err, s) {
|
||||
ErrorHandler.logError(
|
||||
e: err,
|
||||
s: s,
|
||||
data: {
|
||||
'pangeaMessageEvent': pangeaMessageEvent,
|
||||
'messageAnalyticsEntry': messageAnalyticsEntry,
|
||||
'isSelected': isSelected,
|
||||
},
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,419 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter_linkify/flutter_linkify.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/utils/any_state_holder.dart';
|
||||
import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/events/utils/message_text_util.dart';
|
||||
import 'package:fluffychat/pangea/message_token_text/message_token_button.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_selection.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_selection_repo.dart';
|
||||
import 'package:fluffychat/pangea/toolbar/enums/message_mode_enum.dart';
|
||||
import 'package:fluffychat/pangea/toolbar/enums/reading_assistance_mode_enum.dart';
|
||||
import 'package:fluffychat/pangea/toolbar/utils/token_rendering_util.dart';
|
||||
import 'package:fluffychat/pangea/toolbar/widgets/message_selection_overlay.dart';
|
||||
import 'package:fluffychat/utils/url_launcher.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
/// Question - does this need to be stateful or does this work?
|
||||
/// Need to test.
|
||||
///
|
||||
|
||||
class MessageTokenText extends StatelessWidget {
|
||||
final PangeaMessageEvent _pangeaMessageEvent;
|
||||
final TextStyle _style;
|
||||
|
||||
final bool Function(PangeaToken)? _isSelected;
|
||||
final void Function(PangeaToken)? _onClick;
|
||||
final bool Function(PangeaToken)? _isHighlighted;
|
||||
final MessageOverlayController? _overlayController;
|
||||
final bool _isTransitionAnimation;
|
||||
final ReadingAssistanceMode? readingAssistanceMode;
|
||||
|
||||
const MessageTokenText({
|
||||
super.key,
|
||||
required PangeaMessageEvent pangeaMessageEvent,
|
||||
required List<PangeaToken>? tokens,
|
||||
required TextStyle style,
|
||||
required void Function(PangeaToken)? onClick,
|
||||
bool Function(PangeaToken)? isSelected,
|
||||
bool Function(PangeaToken)? isHighlighted,
|
||||
MessageMode? messageMode,
|
||||
MessageOverlayController? overlayController,
|
||||
bool isTransitionAnimation = false,
|
||||
this.readingAssistanceMode,
|
||||
}) : _onClick = onClick,
|
||||
_isSelected = isSelected,
|
||||
_style = style,
|
||||
_pangeaMessageEvent = pangeaMessageEvent,
|
||||
_isHighlighted = isHighlighted,
|
||||
_overlayController = overlayController,
|
||||
_isTransitionAnimation = isTransitionAnimation;
|
||||
|
||||
List<PangeaToken>? get _tokens =>
|
||||
_pangeaMessageEvent.messageDisplayRepresentation?.tokens;
|
||||
|
||||
PracticeSelection? get messageAnalyticsEntry => _tokens != null
|
||||
? PracticeSelectionRepo.get(
|
||||
_pangeaMessageEvent.messageDisplayLangCode,
|
||||
_tokens!,
|
||||
)
|
||||
: null;
|
||||
|
||||
void callOnClick(TokenPosition tokenPosition) {
|
||||
_onClick != null && tokenPosition.token != null
|
||||
? _onClick!(tokenPosition.token!)
|
||||
: null;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_tokens == null) {
|
||||
return Text(
|
||||
_pangeaMessageEvent.messageDisplayText,
|
||||
style: _style,
|
||||
textScaler: TextScaler.noScaling,
|
||||
);
|
||||
}
|
||||
|
||||
return MessageTextWidget(
|
||||
pangeaMessageEvent: _pangeaMessageEvent,
|
||||
existingStyle: _style,
|
||||
messageAnalyticsEntry: messageAnalyticsEntry,
|
||||
isSelected: _isSelected,
|
||||
onClick: callOnClick,
|
||||
isHighlighted: _isHighlighted,
|
||||
overlayController: _overlayController,
|
||||
isTransitionAnimation: _isTransitionAnimation,
|
||||
readingAssistanceMode: readingAssistanceMode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MessageTextWidget extends StatelessWidget {
|
||||
final PangeaMessageEvent pangeaMessageEvent;
|
||||
final TextStyle existingStyle;
|
||||
final PracticeSelection? messageAnalyticsEntry;
|
||||
final bool Function(PangeaToken)? isSelected;
|
||||
final void Function(TokenPosition tokenPosition)? onClick;
|
||||
final bool Function(PangeaToken)? isHighlighted;
|
||||
|
||||
final bool? softWrap;
|
||||
final int? maxLines;
|
||||
final TextOverflow? overflow;
|
||||
|
||||
final MessageOverlayController? overlayController;
|
||||
final bool isTransitionAnimation;
|
||||
final bool isMessage;
|
||||
final ReadingAssistanceMode? readingAssistanceMode;
|
||||
|
||||
final TextScaler? textScaler;
|
||||
|
||||
const MessageTextWidget({
|
||||
super.key,
|
||||
required this.pangeaMessageEvent,
|
||||
required this.existingStyle,
|
||||
this.messageAnalyticsEntry,
|
||||
this.isSelected,
|
||||
this.onClick,
|
||||
this.softWrap,
|
||||
this.maxLines,
|
||||
this.overflow,
|
||||
this.isHighlighted,
|
||||
this.overlayController,
|
||||
this.isTransitionAnimation = false,
|
||||
this.isMessage = true,
|
||||
this.readingAssistanceMode,
|
||||
this.textScaler,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final renderer = TokenRenderingUtil(
|
||||
pangeaMessageEvent: pangeaMessageEvent,
|
||||
readingAssistanceMode: readingAssistanceMode,
|
||||
existingStyle: existingStyle,
|
||||
overlayController: overlayController,
|
||||
isTransitionAnimation: isTransitionAnimation,
|
||||
);
|
||||
|
||||
final Characters messageCharacters =
|
||||
pangeaMessageEvent.messageDisplayText.characters;
|
||||
|
||||
final tokenPositions = MessageTextUtil.getTokenPositions(
|
||||
pangeaMessageEvent,
|
||||
messageAnalyticsEntry: messageAnalyticsEntry,
|
||||
isSelected: isSelected,
|
||||
isHighlighted: isHighlighted,
|
||||
);
|
||||
|
||||
if (tokenPositions == null) {
|
||||
return Text(
|
||||
pangeaMessageEvent.messageDisplayText,
|
||||
style: renderer.style(context),
|
||||
softWrap: softWrap,
|
||||
maxLines: maxLines,
|
||||
overflow: overflow,
|
||||
textScaler: textScaler,
|
||||
);
|
||||
}
|
||||
|
||||
final theme = Theme.of(context);
|
||||
final ownMessage =
|
||||
pangeaMessageEvent.senderId == Matrix.of(context).client.userID;
|
||||
final linkColor = theme.brightness == Brightness.light
|
||||
? theme.colorScheme.primary
|
||||
: ownMessage
|
||||
? theme.colorScheme.onPrimary
|
||||
: theme.colorScheme.onSurface;
|
||||
|
||||
return RichText(
|
||||
softWrap: softWrap ?? true,
|
||||
maxLines: maxLines,
|
||||
overflow: overflow ?? TextOverflow.clip,
|
||||
textScaler: textScaler ?? TextScaler.noScaling,
|
||||
text: TextSpan(
|
||||
children:
|
||||
tokenPositions.mapIndexed((int i, TokenPosition tokenPosition) {
|
||||
final substring = messageCharacters
|
||||
.skip(tokenPosition.start)
|
||||
.take(tokenPosition.end - tokenPosition.start)
|
||||
.toString();
|
||||
|
||||
if (tokenPosition.token?.pos == 'SPACE') {
|
||||
return const TextSpan(text: '\n');
|
||||
}
|
||||
|
||||
if (tokenPosition.token != null) {
|
||||
// if the tokenPosition is a combination of the token and preceding / following punctuation
|
||||
// split them so that only the token itself is highlighted when clicked
|
||||
String start = '';
|
||||
String middle = '';
|
||||
String end = '';
|
||||
|
||||
final startSplitIndex =
|
||||
tokenPosition.tokenStart - tokenPosition.start;
|
||||
final endSplitIndex = tokenPosition.tokenEnd - tokenPosition.start;
|
||||
|
||||
start = substring.characters.take(startSplitIndex).toString();
|
||||
end = substring.characters.skip(endSplitIndex).toString();
|
||||
middle = substring.characters
|
||||
.skip(startSplitIndex)
|
||||
.take(endSplitIndex - startSplitIndex)
|
||||
.toString();
|
||||
|
||||
final token = tokenPosition.token!;
|
||||
|
||||
final tokenWidth = renderer.tokenTextWidthForContainer(
|
||||
context,
|
||||
token.text.content,
|
||||
);
|
||||
|
||||
return WidgetSpan(
|
||||
child: CompositedTransformTarget(
|
||||
link: renderer.assignTokenKey
|
||||
? MatrixState.pAnyState
|
||||
.layerLinkAndKey(token.text.uniqueKey)
|
||||
.link
|
||||
: LayerLinkAndKey(token.hashCode.toString()).link,
|
||||
child: Column(
|
||||
key: renderer.assignTokenKey
|
||||
? MatrixState.pAnyState
|
||||
.layerLinkAndKey(token.text.uniqueKey)
|
||||
.key
|
||||
: null,
|
||||
children: [
|
||||
if (renderer.showCenterStyling)
|
||||
MessageTokenButton(
|
||||
token: token,
|
||||
overlayController: overlayController,
|
||||
textStyle: renderer.style(context),
|
||||
width: tokenWidth,
|
||||
animateIn: isTransitionAnimation,
|
||||
practiceTargetForToken: overlayController
|
||||
?.toolbarMode.associatedActivityType !=
|
||||
null
|
||||
? overlayController?.practiceSelection
|
||||
?.activities(
|
||||
overlayController!
|
||||
.toolbarMode.associatedActivityType!,
|
||||
)
|
||||
.firstWhereOrNull(
|
||||
(a) => a.tokens.contains(token),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: onClick != null
|
||||
? () => onClick?.call(tokenPosition)
|
||||
: null,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
if (start.isNotEmpty)
|
||||
LinkifySpan(
|
||||
text: start,
|
||||
style: renderer.style(
|
||||
context,
|
||||
color: renderer.backgroundColor(
|
||||
context,
|
||||
tokenPosition.selected,
|
||||
),
|
||||
),
|
||||
linkStyle: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
color: linkColor,
|
||||
),
|
||||
onOpen: (url) =>
|
||||
UrlLauncher(context, url.url).launchUrl(),
|
||||
),
|
||||
// tokenPosition.hideContent
|
||||
// ? WidgetSpan(
|
||||
// alignment: PlaceholderAlignment.middle,
|
||||
// child: GestureDetector(
|
||||
// onTap: onClick != null
|
||||
// ? () => onClick?.call(tokenPosition)
|
||||
// : null,
|
||||
// child: HiddenText(
|
||||
// text: middle,
|
||||
// style: style(context),
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// :
|
||||
LinkifySpan(
|
||||
text: middle,
|
||||
style: renderer.style(
|
||||
context,
|
||||
color: renderer.backgroundColor(
|
||||
context,
|
||||
tokenPosition.selected,
|
||||
),
|
||||
),
|
||||
linkStyle: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
color: linkColor,
|
||||
),
|
||||
onOpen: (url) =>
|
||||
UrlLauncher(context, url.url).launchUrl(),
|
||||
),
|
||||
if (end.isNotEmpty)
|
||||
LinkifySpan(
|
||||
text: end,
|
||||
style: renderer.style(
|
||||
context,
|
||||
color: renderer.backgroundColor(
|
||||
context,
|
||||
tokenPosition.selected,
|
||||
),
|
||||
),
|
||||
linkStyle: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
color: linkColor,
|
||||
),
|
||||
onOpen: (url) =>
|
||||
UrlLauncher(context, url.url).launchUrl(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// AnimatedContainer(
|
||||
// duration: const Duration(
|
||||
// milliseconds: AppConfig.overlayAnimationDuration,
|
||||
// ),
|
||||
// height: overlayController != null && isTransitionAnimation
|
||||
// ? 4
|
||||
// : 0,
|
||||
// width: tokenWidth,
|
||||
// child: Container(
|
||||
// color: backgroundColor(context, tokenPosition),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// if ((i > 0 || i < tokenPositions.length - 1) &&
|
||||
// tokenPositions[i + 1].hideContent &&
|
||||
// tokenPositions[i - 1].hideContent) {
|
||||
// return WidgetSpan(
|
||||
// child: GestureDetector(
|
||||
// onTap: onClick != null
|
||||
// ? () => onClick?.call(tokenPosition)
|
||||
// : null,
|
||||
// child: HiddenText(
|
||||
// text: substring,
|
||||
// style: style(context),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
return LinkifySpan(
|
||||
text: substring,
|
||||
style: renderer.style(context),
|
||||
options: const LinkifyOptions(humanize: false),
|
||||
linkStyle: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
onOpen: (url) => UrlLauncher(context, url.url).launchUrl(),
|
||||
);
|
||||
}
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// class HiddenText extends StatelessWidget {
|
||||
// final String text;
|
||||
// final TextStyle style;
|
||||
|
||||
// const HiddenText({
|
||||
// super.key,
|
||||
// required this.text,
|
||||
// required this.style,
|
||||
// });
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// final TextPainter textPainter = TextPainter(
|
||||
// text: TextSpan(text: text, style: style),
|
||||
// textDirection: TextDirection.ltr,
|
||||
// )..layout();
|
||||
|
||||
// final textWidth = textPainter.size.width;
|
||||
// final textHeight = textPainter.size.height;
|
||||
|
||||
// textPainter.dispose();
|
||||
|
||||
// return SizedBox(
|
||||
// height: textHeight,
|
||||
// child: Stack(
|
||||
// children: [
|
||||
// Container(
|
||||
// width: textWidth,
|
||||
// height: textHeight,
|
||||
// color: Colors.transparent,
|
||||
// ),
|
||||
// Positioned(
|
||||
// bottom: 0,
|
||||
// child: Container(
|
||||
// width: textWidth,
|
||||
// height: 1,
|
||||
// color: style.color,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
Loading…
Add table
Reference in a new issue