> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-feature-android-pin-save-thread.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Pinned Messages

> Full-screen list of all messages pinned in a conversation, with jump-to-message and unpin actions.

<Accordion title="AI Integration Quick Reference">
  ```json theme={null}
  {
    "component": "CometChatPinnedMessages",
    "package": "com.cometchat.uikit.kotlin.presentation.pinnedmessages (XML Views) / com.cometchat.uikit.compose.presentation.pinnedmessages.ui (Compose)",
    "xmlElement": "<com.cometchat.uikit.kotlin.presentation.pinnedmessages.CometChatPinnedMessages />",
    "description": "Full-screen list of all messages pinned in a conversation, rendered as real message bubbles, with jump-to-message and long-press row actions (unpin, copy, info, delete).",
    "primaryOutput": {
      "messageClicked": {
        "method": "setOnMessageClickListener",
        "type": "(BaseMessage) -> Unit"
      }
    },
    "methods": {
      "data": {
        "setUser": { "type": "User", "note": "Scope to a one-on-one conversation. Set exactly one of setUser/setGroup." },
        "setGroup": { "type": "Group", "note": "Scope to a group conversation." }
      },
      "callbacks": {
        "setOnMessageClickListener": "(BaseMessage) -> Unit — row tapped; navigate to the message in its conversation",
        "setOnBackClickListener": "() -> Unit — toolbar back pressed"
      }
    },
    "composeParams": {
      "user": "User? — scope to a one-on-one conversation",
      "group": "Group? — scope to a group conversation",
      "onMessageClick": "(BaseMessage) -> Unit",
      "onBackClick": "() -> Unit"
    },
    "events": ["CometChatMessageEvent.MessagePinned", "CometChatMessageEvent.MessageUnpinned"],
    "featureFlag": "CometChatUIKit.isPinMessageEnabled()"
  }
  ```
</Accordion>

## Where It Fits

`CometChatPinnedMessages` is a full-screen component that lists every message pinned in a single conversation, most recently pinned first. Each row renders the actual message bubble — with the sender's avatar, name and date — so pinned media, files and text all look exactly as they do in the chat. Open it from your conversation screen (the [Message Header](/ui-kit/android/message-header) provides a built-in "Pinned messages" menu item for this), and wire `setOnMessageClickListener` to navigate back to the message in context.

Messages are pinned and unpinned from the [Message List](/ui-kit/android/message-list) action sheet; this screen is the read view, plus a long-press menu on each row (Message info, Copy, Unpin, Subscribe/Unsubscribe to thread, Delete).

<Note>
  Pinned messages require the **Pin Message** feature to be enabled for your app. Gate your entry point with `CometChatUIKit.isPinMessageEnabled()`.
</Note>

## Quick Start

<Tabs>
  <Tab title="Kotlin (XML Views)">
    Add the component to your layout XML:

    ```xml activity_pinned_messages.xml lines theme={null}
    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/main"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.cometchat.uikit.kotlin.presentation.pinnedmessages.CometChatPinnedMessages
            android:id="@+id/pinned_messages"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </FrameLayout>
    ```

    Scope it to the conversation and wire the callbacks:

    ```kotlin PinnedMessagesActivity.kt lines theme={null}
    class PinnedMessagesActivity : AppCompatActivity() {

        private lateinit var pinnedMessages: CometChatPinnedMessages

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_pinned_messages)

            pinnedMessages = findViewById(R.id.pinned_messages)

            // Scope to the conversation — set exactly one of user / group
            user?.let { pinnedMessages.setUser(it) }
            group?.let { pinnedMessages.setGroup(it) }

            pinnedMessages.setOnMessageClickListener { message ->
                // Navigate to the message in its conversation,
                // e.g. finish with a result and call messageList.gotoMessage(message.id)
            }

            pinnedMessages.setOnBackClickListener { finish() }
        }
    }
    ```
  </Tab>

  <Tab title="Jetpack Compose">
    ```kotlin lines theme={null}
    CometChatPinnedMessages(
        user = user,          // or group = group — set exactly one
        onMessageClick = { message ->
            // Navigate to the message in its conversation
        },
        onBackClick = { navController.popBackStack() }
    )
    ```
  </Tab>
</Tabs>

## Actions and Events

### Callback Methods

| Method (Views) / Param (Compose)               | Description                                                                                 |
| ---------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `setOnMessageClickListener` / `onMessageClick` | Fired when a row is tapped. Receives the `BaseMessage`; navigate to it in its conversation. |
| `setOnBackClickListener` / `onBackClick`       | Fired when the toolbar back button is pressed.                                              |

### SDK Events (Real-Time, Automatic)

The list keeps itself up to date — when the logged-in user pins or unpins a message anywhere in the app, the row is added or removed without a refetch, via the `MessagePinned` / `MessageUnpinned` events on the UI Kit event bus; see [Events](/ui-kit/android/events). Pins made by other participants appear when the list is next opened or refetched (server-side real-time delivery for pin events is pending rollout).

## Functionality

* **Real bubbles** — each row hosts the message's actual bubble (text, image, video, audio, file), left-aligned with a `name • date` header and the sender's avatar. Your own messages render with the outgoing (primary-color) bubble style and the name **You**.
* **Long-press menu** — long-press a row for message actions: **Message info**, **Copy**, **Unpin**, **Subscribe/Unsubscribe to thread**, and **Delete**. Unpinning asks for confirmation before it is performed.
* **Jump to message** — tapping a row emits the message through the click callback so you can open the conversation and scroll to it.
* **Empty state** — a built-in empty state ("No pinned messages yet") is shown when the conversation has no pinned messages.
* **Read-only** — the screen never marks messages as read and does not affect unread counts or receipts.

## ViewModel

The screen is backed by `CometChatPinnedMessagesViewModel` (in the shared core module), which fetches via `MessagesRequestBuilder().setPinned(true)` scoped to the set user or group, applies optimistic unpin with revert-on-error, and observes the event bus for live upkeep. In Compose you can inject your own instance through the `viewModel` parameter.

## Next Steps

* [Message List](/ui-kit/android/message-list) — where messages are pinned and unpinned, and where the bubble pin indicator appears.
* [Message Header](/ui-kit/android/message-header) — the built-in "Pinned messages" menu entry point.
* [Saved Messages](/ui-kit/android/saved-messages) — the private, cross-conversation counterpart.
* [Pin A Message (SDK)](/sdk/android/v5/pin-message) — the underlying SDK APIs.
