sajanyamaha
sajanyamaha

Reputation: 3198

flutter detect url and show preview

I am trying to make a wats-app like link preview feature , it has two parts ,

  1. Detect URL from text field
  2. Showing preview of that URL

Part 2 has so many plugins to show the preview , but I am stuck with part 1 , how to detect and parse a URL on user typing on textfield .

Also is there a plugin serving both ?

Upvotes: 2

Views: 3314

Answers (3)

Carlos Daniel
Carlos Daniel

Reputation: 2729

I hope that this could help others, talking about step 1:

To detect a URL from the text view, I do the following (taking into consideration that my use case is a chat message in which in the middle of the text could be 1 or several links)

First, having a function that given a String, identify that are URLs:

bool hasURLs(String text) {
  const pattern =
      r"(https?:\/\/(www.)?|www.)([\w-]+.([\w-]+.)?[\w]+)([\w./?=%-]*)";
  final regExp = RegExp(pattern);
  return regExp.hasMatch(text);
}

Then a logic to display the text message with a link or without links:

final hasUrls = formatter.hasURLs(stringMessage);

In a widget:

return hasUrls
      ? UrlMessage(
          textContent: messageContents,
          textColor: textColor,
          isMyMessage: isMyMessage,
        )
      : Text(
          messageContents,
          style: TextStyle(color: textColor, fontSize: 13),
        );

For UrlMessage widget the code as follows:

class UrlMessage extends StatefulWidget {
  const UrlMessage({
    Key? key,
    required this.textContent,
    required this.textColor,
    required this.isMyMessage,
  }) : super(key: key);

  final String textContent;
  final Color textColor;
  final bool isMyMessage;

  @override
  State<UrlMessage> createState() => _UrlMessageState();

}

class _UrlMessageState extends State<UrlMessage> {
  final formatter = Formatter();

  @override
  Widget build(BuildContext context) {
    final text = widget.textContent;
    final textColor = widget.textColor;
    final isMyMessage = widget.isMyMessage;

    final linkTextStyle = TextStyle(
      color: isMyMessage ? Colors.blueGrey : Colors.blue,
      fontSize: 13,
      fontWeight: FontWeight.bold,
      decoration: TextDecoration.underline,
    );

    return RichText(
      // map each word of the message, ask if it is a URL then set it with each 
      // TextSpan as a link or not. If it's a link use launchUrl from `url_launcher` 
      // package to open it 
      text: TextSpan(
        children: text.split(' ').map((word) {
          // Check for URLs
          if (formatter.hasURLs(word)) {
            return TextSpan(
              text: word,
              style: linkTextStyle,
              recognizer: TapGestureRecognizer()
                ..onTap = () {
                  // Handle link - here we use `url_launcher`
                  launchUrl(Uri.parse(word));
                },
            );
          } else {
            return TextSpan(
              text: '$word ',
              style: TextStyle(color: textColor, fontSize: 13),
            );
          }
        }).toList(),
      ),
    );
  }
}

Regarding step 2, there are several options to work with the preview, in our case Any Link Preview does what we need

Upvotes: 0

Kamlesh
Kamlesh

Reputation: 6145

Detect URLs in String/Paragraph and convert them in links in DART:

//
String convertStringToLink(String textData) {
  // 
  final urlRegExp = new RegExp(
  r"((https?:www\.)|(https?:\/\/)|(www\.))[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9]{1,6}(\/[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)?");
  final urlMatches = urlRegExp.allMatches(textData);
  List<String> urls = urlMatches.map(
          (urlMatch) => textData.substring(urlMatch.start, urlMatch.end))
      .toList();
  List linksString = [];
  urls.forEach((String linkText){
    linksString.add(linkText);
  });

  if (linksString.length > 0) {
    linksString.forEach((linkTextData) {
      textData = textData.replaceAll(
          linkTextData,
          '<a href="' +
              linkTextData +
              '" target="_blank">' +
              linkTextData +
              '</a>');
    });
  }
  return textData;
}

Demo and how to call

String text = "This is my website url: https://github.com/ Google search using: www.google.com, Flutter url: http://example.com/method?param=flutter stackoverflow website url is https://www.stackoverflow.com is greatest website and also check this hashed url https://support.google.com/firebase?authuser=0#topic=6399725";

print(convertStringToLink(text));

Output:

This is my website url: <a href="https://github.com/" target="_blank">https://github.com/</a> Google search using: <a href="www.google.com" target="_blank">www.google.com</a>, Flutter url: <a href="http://example.com/method?param=flutter" target="_blank">http://example.com/method?param=flutter</a> stackoverflow website url is <a href="https://www.stackoverflow.com" target="_blank">https://www.stackoverflow.com</a> is greatest website and also check this hashed url <a href="https://support.google.com/firebase?authuser=0#topic=6399725" target="_blank">https://support.google.com/firebase?authuser=0#topic=6399725</a>

It worked for me, will definitely help my friends :)

Upvotes: 4

jeugene
jeugene

Reputation: 231

You could try Uri.parse(). Do check the link https://www.geeksforgeeks.org/dart-uris/

Get the value from the textfield Using onChanged function and controller

https://medium.com/flutter-community/a-deep-dive-into-flutter-textfields-f0e676aaab7a

Upvotes: -2

Related Questions