Cretezy / flutter_linkify

Turns text URLs and emails into clickable inline links in text for Flutter
https://pub.dartlang.org/packages/flutter_linkify
MIT License
262 stars 99 forks source link

Custom links #124

Open Ai-Kiwi opened 10 months ago

Ai-Kiwi commented 10 months ago

Is there/there should be, a way to create custom links for things such as going @userId, ideally the system would then replace the userId which is the real text with the username and allow it to be clickable and run whatever code you have.

Vov4yk commented 6 months ago

Hello @Ai-Kiwi , I'm working on the same task. It looks like the library allow us to do it in our code. (there are snippets just to give the idea how to work, code could be optimized)

  1. Create own LinkableElement
class MentionElement extends LinkableElement {
  MentionElement(String url, this.mention, [String? text]) : super(text, url);
  final MentionedChatUser mention;

  @override
  String toString() {
    return "MentionElement: '$url' ($text)";
  }

  @override
  bool operator ==(other) => equals(other);

  @override
  bool equals(other) => other is MentionElement && super.equals(other);
}
  1. Create own linkifier
class MentionLinkifier extends Linkifier {
  final List<MentionedChatUser> mentions;

  MentionLinkifier({required this.mentions});

  @override
  List<LinkifyElement> parse(
    List<LinkifyElement> elements,
    LinkifyOptions options,
  ) {
    final list = <LinkifyElement>[];

    elements.forEach((element) {
      String objText = element.text;
      if (element is TextElement && mentions.isNotEmpty) {
        final atIndex = element.text.indexOf('@');
        if (atIndex >= 0) {
          if (atIndex != 0) {
            list.add(TextElement(objText.substring(0, atIndex)));
            objText = objText.substring(atIndex);
          }
          final comps = objText.split(' ');
          final mention =
              mentions.firstWhereOrNull((e) => '@${e.tag}' == comps.first);
          if (mention != null) {
            list.add(MentionElement('${mention.user.name}', mention));
          } else {
            list.add(TextElement('@'));
          }
          if (comps.length > 1) {
            final toCut = '@${mention?.tag ?? ''}';
            list.addAll(
                parse([TextElement(objText.substring(toCut.length))], options));
          }
        } else {
          list.add(TextElement(objText));
        }
      } else {
        list.add(element);
      }
    });
    return list;
  }
}
  1. Add yours linkifier during Linkify object creation

    linkifiers: [
        const UrlLinkifier(),
        const EmailLinkifier(),
        if (mentions.isNotEmpty) MentionLinkifier(mentions: mentions),
      ],
  2. Add some logic to onOpen

onOpen: (link) async {
        UrlLaunchHelper.tryLaunch(context, link.url);
        if (link is MentionLinkifier) {
          ...
        }
      },