parseLinks method
- List<
TapGestureRecognizer> recognizers, [ - TextStyle? style
Returns TextSpans containing plain text along with links and e-mails detected and parsed.
recognizers are TapGestureRecognizers constructed, so ensure to
dispose them properly.
Implementation
TextSpan parseLinks(
List<TapGestureRecognizer> recognizers, [
TextStyle? style,
]) {
final Iterable<RegExpMatch> matches = [
..._regex.allMatches(this),
...UserNum.sourceExp.allMatches(this),
].sorted((a, b) => a.start.compareTo(b.start));
if (matches.isEmpty) {
return TextSpan(text: this);
}
String text = this;
final List<TextSpan> spans = [];
final List<String> links = [];
for (RegExpMatch match in matches) {
links.add(text.substring(match.start, match.end));
}
for (int i = 0; i < links.length; i++) {
final String link = links[i];
final int index = text.indexOf(link);
if (index == -1) {
continue;
}
final List<String> parts = [
text.substring(0, index),
text.substring(index + link.length),
];
if (parts[0].isNotEmpty) {
spans.add(TextSpan(text: parts[0]));
}
final TapGestureRecognizer recognizer = TapGestureRecognizer();
recognizers.add(recognizer);
spans.add(
TextSpan(
text: link,
style: style,
recognizer: recognizer
..onTap = () async {
Uri? uri;
final bool isNum = UserNum.sourceExp.hasMatch(link);
if (isNum) {
final UserNum? parsed = UserNum.tryParse(link);
if (parsed != null) {
return router.chat(ChatId(link), mode: RouteAs.push);
}
} else if (link.isEmail) {
uri = Uri(scheme: 'mailto', path: link);
} else {
uri = Uri.parse(
!link.startsWith('http') ? 'https://$link' : link,
);
final String url = uri.toString();
final List<String> origins = [Config.origin, Config.link];
for (var e in origins) {
if (url.startsWith(e)) {
if (e.endsWith(Routes.directLink)) {
return router.push(
url.replaceFirst(
e.substring(0, e.length - Routes.directLink.length),
'',
),
);
}
return router.push(url.replaceFirst(e, ''));
}
}
}
if (uri != null) {
if (await canLaunchUrl(uri)) {
await launchUrl(uri);
}
}
},
),
);
if (parts[1].isNotEmpty) {
if (i == links.length - 1) {
spans.add(TextSpan(text: parts[1]));
} else {
text = parts[1];
}
}
}
return TextSpan(children: spans);
}