> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-rn-guide-message-privately.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# URL Formatter

> Detect and style plain URLs as clickable links with optional tracking logic in CometChat Flutter UI Kit.

<Accordion title="AI Agent Component Spec">
  | Field          | Value                                                                                                                      |
  | -------------- | -------------------------------------------------------------------------------------------------------------------------- |
  | Package        | `cometchat_chat_uikit`                                                                                                     |
  | Key class      | `CometChatUrlFormatter` (extends `CometChatTextFormatter`)                                                                 |
  | Required setup | `CometChatUIKit.init(uiKitSettings: uiKitSettings)` then `CometChatUIKit.login("UID")`                                     |
  | Purpose        | Auto-detects URLs in text messages and converts them to clickable links                                                    |
  | Sample app     | [GitHub](https://github.com/cometchat/cometchat-uikit-flutter/tree/v5/sample_app)                                          |
  | Related        | [Custom Text Formatter](/ui-kit/flutter/v5/custom-text-formatter-guide) \| [All Guides](/ui-kit/flutter/v5/guide-overview) |
</Accordion>

`CometChatUrlFormatter` extends [CometChatTextFormatter](/ui-kit/flutter/v5/custom-text-formatter-guide) to detect URLs in text messages and render them as clickable links.

***

## Overview

The URL formatter is included by default in the Flutter UI Kit. It automatically:

* Detects URLs in message text using regex patterns
* Styles URLs with underline and link color
* Opens URLs in the browser when tapped

***

## Default Behavior

The `CometChatUrlFormatter` is automatically applied to messages. URLs are:

* Styled with underline decoration
* Colored based on bubble alignment (white for outgoing, info color for incoming)
* Clickable - tapping opens the URL in the default browser

***

## Usage

### Basic Usage (Default)

The URL formatter is included by default. No additional setup required.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: chatUser,
      // URL formatter is automatically included
    )
    ```
  </Tab>
</Tabs>

### Custom URL Formatter

Create a custom URL formatter with your own styling and behavior.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
    import 'package:flutter/material.dart';
    import 'package:url_launcher/url_launcher.dart';

    class CustomUrlFormatter extends CometChatUrlFormatter {
      CustomUrlFormatter() : super(
        pattern: RegExp(r'(https?:\/\/[^\s]+)'),
        messageBubbleTextStyle: (context, alignment, {forConversation}) {
          return TextStyle(
            color: Colors.blue,
            decoration: TextDecoration.underline,
            decorationColor: Colors.blue,
          );
        },
      );

      @override
      List<AttributedText> getAttributedText(
        String text, 
        BuildContext context, 
        BubbleAlignment? alignment,
        {List<AttributedText>? existingAttributes,
        Function(String)? onTap,
        bool forConversation = false}
      ) {
        return super.getAttributedText(
          text, context, alignment,
          existingAttributes: existingAttributes,
          onTap: onTap ?? (url) async {
            // Custom URL handling
            _trackUrlClick(url);
            await _openUrl(url);
          },
          forConversation: forConversation,
        );
      }

      void _trackUrlClick(String url) {
        // Add analytics tracking
        print('URL clicked: $url');
      }

      Future<void> _openUrl(String url) async {
        if (!url.startsWith('http://') && !url.startsWith('https://')) {
          url = 'https://$url';
        }
        final uri = Uri.parse(url);
        if (await canLaunchUrl(uri)) {
          await launchUrl(uri, mode: LaunchMode.externalApplication);
        }
      }
    }
    ```
  </Tab>
</Tabs>

### Apply Custom Formatter

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: chatUser,
      textFormatters: [
        CustomUrlFormatter(),
        CometChatMentionsFormatter(), // Keep other formatters
      ],
    )
    ```
  </Tab>
</Tabs>

***

## Customization

### Styling Links

Override `getMessageBubbleTextStyle` to customize link appearance:

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    @override
    TextStyle getMessageBubbleTextStyle(
      BuildContext context, 
      BubbleAlignment? alignment,
      {bool forConversation = false}
    ) {
      CometChatColorPalette colorPalette = CometChatThemeHelper.getColorPalette(context);
      
      return TextStyle(
        color: alignment == BubbleAlignment.right 
          ? colorPalette.white 
          : colorPalette.info,
        fontWeight: FontWeight.w500,
        decoration: TextDecoration.underline,
        decorationColor: alignment == BubbleAlignment.right 
          ? colorPalette.white 
          : colorPalette.info,
      );
    }
    ```
  </Tab>
</Tabs>

### Custom URL Pattern

Use a custom regex pattern to match specific URL formats:

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatUrlFormatter(
      pattern: RegExp(
        r'(https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*))'
      ),
    )
    ```
  </Tab>
</Tabs>

### Handle URL Clicks

Override `getAttributedText` to add custom click handling:

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    @override
    List<AttributedText> getAttributedText(
      String text, 
      BuildContext context, 
      BubbleAlignment? alignment,
      {List<AttributedText>? existingAttributes,
      Function(String)? onTap,
      bool forConversation = false}
    ) {
      return super.getAttributedText(
        text, context, alignment,
        existingAttributes: existingAttributes,
        onTap: (url) async {
          // Show confirmation dialog before opening
          final shouldOpen = await showDialog<bool>(
            context: context,
            builder: (context) => AlertDialog(
              title: Text('Open Link'),
              content: Text('Open $url?'),
              actions: [
                TextButton(
                  onPressed: () => Navigator.pop(context, false),
                  child: Text('Cancel'),
                ),
                TextButton(
                  onPressed: () => Navigator.pop(context, true),
                  child: Text('Open'),
                ),
              ],
            ),
          );
          
          if (shouldOpen == true) {
            await launchUrl(Uri.parse(url));
          }
        },
        forConversation: forConversation,
      );
    }
    ```
  </Tab>
</Tabs>

***

## Properties

| Property                 | Type        | Description                              |
| ------------------------ | ----------- | ---------------------------------------- |
| `pattern`                | `RegExp?`   | Regex pattern to match URLs              |
| `messageBubbleTextStyle` | `Function?` | Custom style for URL text in bubbles     |
| `onSearch`               | `Function?` | Callback when URL is detected            |
| `showLoadingIndicator`   | `bool?`     | Show loading indicator during processing |

***

## Complete Example

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
    import 'package:flutter/material.dart';
    import 'package:url_launcher/url_launcher.dart';

    class UrlFormatterExample extends StatefulWidget {
      const UrlFormatterExample({super.key});

      @override
      State<UrlFormatterExample> createState() => _UrlFormatterExampleState();
    }

    class _UrlFormatterExampleState extends State<UrlFormatterExample> {
      User? chatUser;

      @override
      void initState() {
        super.initState();
        CometChat.getUser("uid").then((user) {
          setState(() => chatUser = user);
        });
      }

      @override
      Widget build(BuildContext context) {
        if (chatUser == null) {
          return const Center(child: CircularProgressIndicator());
        }

        return Scaffold(
          body: CometChatMessageList(
            user: chatUser,
            textFormatters: [
              CometChatUrlFormatter(
                messageBubbleTextStyle: (context, alignment, {forConversation}) {
                  return TextStyle(
                    color: alignment == BubbleAlignment.right 
                      ? Colors.white 
                      : Colors.blue,
                    decoration: TextDecoration.underline,
                  );
                },
              ),
              CometChatMentionsFormatter(),
            ],
          ),
        );
      }
    }
    ```
  </Tab>
</Tabs>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Custom Text Formatter" href="/ui-kit/flutter/v5/custom-text-formatter-guide">
    Build custom inline text patterns.
  </Card>

  <Card title="Message List" href="/ui-kit/flutter/v5/message-list">
    Render real-time message threads.
  </Card>

  <Card title="All Guides" href="/ui-kit/flutter/v5/guide-overview">
    Browse all feature and formatter guides.
  </Card>

  <Card title="Sample App" href="https://github.com/cometchat/cometchat-uikit-flutter/tree/v5/sample_app">
    Full working sample application on GitHub.
  </Card>
</CardGroup>
