-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat(link): add highlighting links and open them. * fix(admin): handle fetching users when being an admin.
- Loading branch information
1 parent
2f9d470
commit 6beeaaf
Showing
3 changed files
with
251 additions
and
16 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import 'package:flutter/gestures.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:url_launcher/url_launcher.dart'; | ||
|
||
class LinkTextField extends StatefulWidget { | ||
final TextEditingController controller; | ||
final bool notAllowedToSend; | ||
|
||
const LinkTextField({ | ||
Key? key, | ||
required this.controller, | ||
this.notAllowedToSend = false, | ||
}) : super(key: key); | ||
|
||
@override | ||
_LinkTextFieldState createState() => _LinkTextFieldState(); | ||
} | ||
|
||
class _LinkTextFieldState extends State<LinkTextField> { | ||
final FocusNode _textFieldFocusNode = FocusNode(); | ||
bool isTextEmpty = true; | ||
bool _emojiShowing = false; | ||
final RegExp _linkRegExp = RegExp( | ||
r'((https?|ftp)://[^\s/$.?#].[^\s]*)', | ||
caseSensitive: false, | ||
); | ||
|
||
Future<void> _launchURL(String url) async { | ||
final Uri uri = Uri.parse(url); | ||
if (await canLaunchUrl(uri)) { | ||
await launchUrl(uri, mode: LaunchMode.externalApplication); | ||
} else { | ||
throw 'Could not launch $url'; | ||
} | ||
} | ||
|
||
List<TextSpan> _buildTextSpans(String text) { | ||
List<TextSpan> spans = []; | ||
int start = 0; | ||
|
||
_linkRegExp.allMatches(text).forEach((match) { | ||
if (match.start > start) { | ||
spans.add(TextSpan(text: text.substring(start, match.start))); | ||
} | ||
final String url = match.group(0)!; | ||
spans.add( | ||
TextSpan( | ||
text: url, | ||
style: const TextStyle( | ||
color: Colors.blue, decoration: TextDecoration.underline), | ||
recognizer: TapGestureRecognizer()..onTap = () => _launchURL(url), | ||
), | ||
); | ||
start = match.end; | ||
}); | ||
|
||
if (start < text.length) { | ||
spans.add(TextSpan(text: text.substring(start))); | ||
} | ||
|
||
return spans; | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Column( | ||
children: [ | ||
TextField( | ||
focusNode: _textFieldFocusNode, | ||
controller: widget.controller, | ||
enabled: !widget.notAllowedToSend, | ||
decoration: InputDecoration( | ||
hintText: widget.notAllowedToSend ? 'Text not Allowed' : 'Message', | ||
hintStyle: const TextStyle( | ||
fontSize: 18, | ||
color: Colors.grey, | ||
fontWeight: FontWeight.w400, | ||
), | ||
border: InputBorder.none, | ||
focusedBorder: InputBorder.none, | ||
enabledBorder: InputBorder.none, | ||
prefixIcon: widget.notAllowedToSend | ||
? const Icon( | ||
Icons.lock, | ||
color: Colors.grey, | ||
) | ||
: null, | ||
), | ||
cursorColor: Colors.blue, | ||
onTap: () { | ||
if (widget.notAllowedToSend) return; | ||
setState(() { | ||
_emojiShowing = false; | ||
}); | ||
}, | ||
onChanged: (text) { | ||
if (isTextEmpty ^ text.isEmpty) { | ||
setState(() { | ||
isTextEmpty = text.isEmpty; | ||
}); | ||
} | ||
}, | ||
), | ||
if (widget.controller.text.isNotEmpty) | ||
Container( | ||
padding: const EdgeInsets.all(8.0), | ||
alignment: Alignment.topLeft, | ||
child: RichText( | ||
text: TextSpan( | ||
style: const TextStyle(fontSize: 18, color: Colors.black), | ||
children: _buildTextSpans(widget.controller.text), | ||
), | ||
), | ||
), | ||
], | ||
); | ||
} | ||
} |
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