@@ -10,7 +10,7 @@ import 'package:linkable/parser.dart';
1010import 'package:linkable/telParser.dart' ;
1111import 'package:url_launcher/url_launcher.dart' ;
1212
13- class Linkable extends StatefulWidget {
13+ class Linkable extends StatelessWidget {
1414 final String text;
1515
1616 final textColor;
@@ -39,6 +39,9 @@ class Linkable extends StatefulWidget {
3939
4040 final textHeightBehavior;
4141
42+ List <Parser > _parsers = List <Parser >();
43+ List <Link > _links = List <Link >();
44+
4245 Linkable ({
4346 Key key,
4447 @required this .text,
@@ -57,118 +60,74 @@ class Linkable extends StatefulWidget {
5760 this .textHeightBehavior,
5861 }) : super (key: key);
5962
60- @override
61- _LinkableState createState () => _LinkableState ();
62- }
63-
64- class _LinkableState extends State <Linkable > {
65- List <Parser > _parsers = List <Parser >();
66- List <Link > _links = List <Link >();
67-
68- @override
69- void initState () {
70- super .initState ();
71- _addParsers ();
72- _parseLinks ();
73- _filterLinks ();
74- }
75-
7663 @override
7764 Widget build (BuildContext context) {
65+ init ();
7866 return RichText (
79- textAlign: widget. textAlign,
80- textDirection: widget. textDirection,
81- softWrap: widget. softWrap,
82- overflow: widget. overflow,
83- textScaleFactor: widget. textScaleFactor,
84- maxLines: widget. maxLines,
85- locale: widget. locale,
86- strutStyle: widget. strutStyle,
87- textWidthBasis: widget. textWidthBasis,
88- textHeightBehavior: widget. textHeightBehavior,
67+ textAlign: textAlign,
68+ textDirection: textDirection,
69+ softWrap: softWrap,
70+ overflow: overflow,
71+ textScaleFactor: textScaleFactor,
72+ maxLines: maxLines,
73+ locale: locale,
74+ strutStyle: strutStyle,
75+ textWidthBasis: textWidthBasis,
76+ textHeightBehavior: textHeightBehavior,
8977 text: TextSpan (
9078 text: '' ,
91- style: widget. style,
79+ style: style,
9280 children: _getTextSpans (),
9381 ),
9482 );
9583 }
9684
97- _addParsers () {
98- _parsers.add (EmailParser (widget.text));
99- _parsers.add (HttpParser (widget.text));
100- _parsers.add (TelParser (widget.text));
101- }
102-
103- _parseLinks () {
104- for (Parser parser in _parsers) {
105- _links.addAll (parser.parse ().toList ());
106- }
107- }
108-
109- _filterLinks () {
110- _links.sort (
111- (Link a, Link b) => a.regExpMatch.start.compareTo (b.regExpMatch.start));
112-
113- List <Link > _filteredLinks = List <Link >();
114- if (_links.length > 0 ) {
115- _filteredLinks.add (_links[0 ]);
116- }
117-
118- for (int i = 0 ; i < _links.length - 1 ; i++ ) {
119- if (_links[i + 1 ].regExpMatch.start > _links[i].regExpMatch.end) {
120- _filteredLinks.add (_links[i + 1 ]);
121- }
122- }
123- _links = _filteredLinks;
124- }
125-
12685 _getTextSpans () {
12786 List <TextSpan > _textSpans = List <TextSpan >();
12887 int i = 0 ;
12988 int pos = 0 ;
130- while (i < widget. text.length) {
131- _textSpans.add (_text (widget. text.substring (
89+ while (i < text.length) {
90+ _textSpans.add (_text (text.substring (
13291 i,
133- pos < _links.length && i < _links[pos].regExpMatch.start
92+ pos < _links.length && i <= _links[pos].regExpMatch.start
13493 ? _links[pos].regExpMatch.start
135- : widget. text.length)));
136- if (pos < _links.length && i < _links[pos].regExpMatch.start) {
94+ : text.length)));
95+ if (pos < _links.length && i <= _links[pos].regExpMatch.start) {
13796 _textSpans.add (_link (
138- widget. text.substring (
97+ text.substring (
13998 _links[pos].regExpMatch.start, _links[pos].regExpMatch.end),
14099 _links[pos].type));
141100 i = _links[pos].regExpMatch.end;
142101 pos++ ;
143102 } else {
144- i = widget. text.length;
103+ i = text.length;
145104 }
146105 }
147106 return _textSpans;
148107 }
149108
150- _launch (String url) async {
151- if (await canLaunch (url)) {
152- await launch (url);
153- } else {
154- throw 'Could not launch $url ' ;
155- }
156- }
157-
158109 _text (String text) {
159- return TextSpan (text: text, style: TextStyle (color: widget. textColor));
110+ return TextSpan (text: text, style: TextStyle (color: textColor));
160111 }
161112
162113 _link (String text, String type) {
163114 return TextSpan (
164115 text: text,
165- style: TextStyle (color: widget. linkColor),
116+ style: TextStyle (color: linkColor),
166117 recognizer: TapGestureRecognizer ()
167118 ..onTap = () {
168119 _launch (_getUrl (text, type));
169120 });
170121 }
171122
123+ _launch (String url) async {
124+ if (await canLaunch (url)) {
125+ await launch (url);
126+ } else {
127+ throw 'Could not launch $url ' ;
128+ }
129+ }
130+
172131 _getUrl (String text, String type) {
173132 switch (type) {
174133 case http:
@@ -181,4 +140,40 @@ class _LinkableState extends State<Linkable> {
181140 return text;
182141 }
183142 }
143+
144+ init () {
145+ _addParsers ();
146+ _parseLinks ();
147+ _filterLinks ();
148+ }
149+
150+ _addParsers () {
151+ _parsers.add (EmailParser (text));
152+ _parsers.add (HttpParser (text));
153+ _parsers.add (TelParser (text));
154+ }
155+
156+ _parseLinks () {
157+ for (Parser parser in _parsers) {
158+ _links.addAll (parser.parse ().toList ());
159+ }
160+ }
161+
162+ _filterLinks () {
163+ _links.sort (
164+ (Link a, Link b) =>
165+ a.regExpMatch.start.compareTo (b.regExpMatch.start));
166+
167+ List <Link > _filteredLinks = List <Link >();
168+ if (_links.length > 0 ) {
169+ _filteredLinks.add (_links[0 ]);
170+ }
171+
172+ for (int i = 0 ; i < _links.length - 1 ; i++ ) {
173+ if (_links[i + 1 ].regExpMatch.start > _links[i].regExpMatch.end) {
174+ _filteredLinks.add (_links[i + 1 ]);
175+ }
176+ }
177+ _links = _filteredLinks;
178+ }
184179}
0 commit comments