Created
August 23, 2018 17:12
-
-
Save long1eu/070517dbd20cf4fd1bab75803f3fe5b1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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