Skip to content

Instantly share code, notes, and snippets.

@long1eu
Created August 23, 2018 17:12
Show Gist options
  • Save long1eu/070517dbd20cf4fd1bab75803f3fe5b1 to your computer and use it in GitHub Desktop.
Save long1eu/070517dbd20cf4fd1bab75803f3fe5b1 to your computer and use it in GitHub Desktop.
import 'package:engine_io_client/engine_io_client.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
final RegExp urlRegEx = new RegExp(r'(https?://)?(www\.)?([\w]+\.)+[‌​\w]{2,63}/?');
final RegExp phoneRegEx =
new RegExp(r'(([(]?(\d{2,4})[)]?)|(\d{2,4})|([+1-9]+\d{1,2}))?[-\s]?(\d{2,3})?[-\s]?((\d{7,8})|(\d{3,4}[-\s]\d{3,4}))');
RegExp emailRegEx = new RegExp(r'[a-zA-Z0-9-_.]+@[a-zA-Z0-9-_.]+');
RegExp underline = new RegExp(r'__(.*?)__');
RegExp italic = new RegExp(r'_(.*?)_');
RegExp bold = new RegExp(r'\*(.*?)\*');
RegExp strikethrough = new RegExp(r'~(.*?)~');
enum ItemType { email, url, phone }
typedef void OnItemTapped(String item, ItemType type);
class MessagesParser {
static final Log log = new Log('MessagesParser');
const MessagesParser();
static TextSpan parse(String message, OnItemTapped onItemTapped) {
return _match(
regex: emailRegEx,
text: message,
style: const TextStyle(
color: Colors.blue,
decoration: TextDecoration.underline,
),
onItemTapped: onItemTapped,
nextMatcher: (String text) {
return _match(
regex: urlRegEx,
text: text,
style: const TextStyle(
color: Colors.blue,
decoration: TextDecoration.underline,
),
onItemTapped: onItemTapped,
nextMatcher: (String text) {
return _match(
regex: phoneRegEx,
text: text,
style: const TextStyle(
color: Colors.blue,
decoration: TextDecoration.underline,
),
onItemTapped: onItemTapped,
nextMatcher: (String text) {
return _match(
regex: underline,
text: text,
style: const TextStyle(
decoration: TextDecoration.underline,
),
onItemTapped: onItemTapped,
nextMatcher: (String text) {
return _match(
regex: italic,
text: text,
style: const TextStyle(
fontStyle: FontStyle.italic,
),
onItemTapped: onItemTapped,
nextMatcher: (String text) {
return _match(
regex: bold,
text: text,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
onItemTapped: onItemTapped,
nextMatcher: (String text) {
return _match(
regex: strikethrough,
text: text,
style: const TextStyle(
decoration: TextDecoration.lineThrough,
),
onItemTapped: onItemTapped,
);
},
);
},
);
},
);
},
);
},
);
},
);
}
static TextSpan _match({
RegExp regex,
String text,
TextStyle style,
OnItemTapped onItemTapped,
TextSpan nextMatcher(String text) = _nextMatcher,
}) {
final List<Match> matches = regex.allMatches(text).toList(growable: false);
TextSpan textSpan =
new TextSpan(children: <TextSpan>[].toList(growable: true), style: const TextStyle(color: Colors.black87));
if (matches.isNotEmpty) {
int previousEnd = 0;
for (Match m in matches) {
final String beforePart = text.substring(previousEnd, m.start);
if (beforePart.isNotEmpty) textSpan.children.add(nextMatcher(beforePart));
textSpan.children.add(
new TextSpan(
text: m.groupCount == 1 ? m.group(1) : m.group(0),
style: style,
recognizer: new TapGestureRecognizer()
..onTap = () {
final ItemType itemType =
regex == emailRegEx ? ItemType.email : regex == urlRegEx ? ItemType.url : ItemType.phone;
onItemTapped(m.group(0), itemType);
},
),
);
if (m == matches.last) {
final String afterPart = text.substring(m.end);
if (afterPart.isNotEmpty) textSpan.children.add(nextMatcher(afterPart));
}
previousEnd = m.end;
}
} else {
textSpan = nextMatcher(text);
}
return textSpan;
}
static TextSpan _nextMatcher(String text) => new TextSpan(text: text);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment