Implement Pin Message Feature in React UI Kit

This guide helps you to implement the Pin Message functionality using the React UI Kit.

Prerequisites

  • You must have CometChat React UI Kit integrated in your project.
  • The pin-message extension should be enabled in your CometChat dashboard.

:puzzle_piece: Step-by-Step Implementation

1. Maintain a State to Store Pinned Messages

Use the useState hook to manage the list of pinned messages.

const [pinnedMessages, setPinnedMessages] = useState<any[]>([]);

2. Create a Function to Fetch Pinned Messages

Fetch pinned messages from the extension and update the state.


const fetchPinnedMessages = () => {
  const URL = `v1/fetch?receiverType=user&receiver=${user.getUid()}`;
  CometChat.callExtension('pin-message', 'GET', URL, {})
    .then((response: any) => {
      setPinnedMessages(response['pinnedMessages']);
    })
    .catch((error: any) => {
      console.log("failed to fetch pinnedMessage ->", error);
    });
};

useEffect(() => {
  fetchPinnedMessages();
}, []);

3. Add Pin/Unpin Options to Message Actions

Modify the options shown on each message to include “Pin” or “Unpin” based on the message’s status.

const getOptions = (
  loggedInUser: CometChat.User,
  message: CometChat.BaseMessage,
  theme: CometChatTheme,
  group?: CometChat.Group,
) => {
  const defaultMessageOptions = CometChatUIKit
    .getDataSource()
    .getMessageOptions(loggedInUser, message, theme, group);

  const isPinned = pinnedMessages.find((ele: any) => ele.id === message.getId());

  const pinOption = new CometChatActionsIcon({
    id: "pin_message",
    title: "PIN",
    iconURL: "https://png.pngtree.com/png-clipart/20230217/ourmid/pngtree-paper-red-pin-transparent-vector-png-image_6605001.png",
    onClick: () => {
      CometChat.callExtension('pin-message', 'POST', 'v1/pin', {
        msgId: message.getId(),
      }).then(() => {
        setPinnedMessages((prev: any) => [...prev, message]);
      }).catch(error => {
        console.log("unable to pin message", error);
      });
    },
    iconTint: "red"
  });

  const unPinOption = new CometChatActionsIcon({
    id: "unpin_message",
    title: "UNPIN",
    iconURL: "https://static.thenounproject.com/png/1713712-200.png",
    onClick: () => {
      CometChat.callExtension('pin-message', 'DELETE', 'v1/unpin', {
        msgId: message.getId(),
        receiverType: message.getReceiverType(),
        receiver: user.getUid(),
      }).then(() => {
        fetchPinnedMessages(); // Or filter out the message manually
      }).catch(error => {
        console.log("unable to unpin message", error);
      });
    },
    iconTint: "lime"
  });

  isPinned ? defaultMessageOptions.unshift(unPinOption) : defaultMessageOptions.unshift(pinOption);

  return defaultMessageOptions;
};


4. Inject Options into Message Templates

Override the default templates to include the custom pin/unpin options.


const getTemplates = () => {
  let definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(new CometChatTheme());

  definedTemplates.map(template => {
    template.options = (loggedInUser, message, theme, group) =>
      getOptions(loggedInUser, message, theme, group);
  });

  return definedTemplates;
};


5. Handle the Fetch of Pinned Messages (Optional Header Button)

Create a utility function to fetch pinned messages on demand (e.g., from a button).


const getPins = (user: CometChat.User | undefined, group: CometChat.Group | undefined) => {
  const receiverType = user ? "user" : "group";
  const receiver = user ? user.getUid() : group?.getGuid();

  const URL = `v1/fetch?receiverType=${receiverType}&receiver=${receiver}`;
  CometChat.callExtension('pin-message', 'GET', URL, {})
    .then((response: any) => {
      console.log("pinned messages ->", response['pinnedMessages']);
    })
    .catch(error => {
      console.log("failed to fetch pinnedMessage ->", error);
    });
};


6. Customize Message Header View (Show Pinned Button)

Inject a “Pins” button in the message header to manually trigger fetch.

const getHeaderView = (user: CometChat.User, group: CometChat.Group) => {
  const defaultAuxiliaryMenu = ChatConfigurator.getDataSource().getAuxiliaryHeaderMenu(user, group);

  return (
    <CometChatMessageHeader
      user={user}
      group={group}
      menu={
        <div style={{ display: "flex", justifyContent: "space-between" }}>
          <button onClick={() => getPins(user, group)}>Pins</button>
          {defaultAuxiliaryMenu.map((auxMenu: any) => auxMenu)}
        </div>
      }
    />
  );
};


7. Configure Message List and Pass Props

Set up the message list configuration and pass it to the CometChatMessages component.

const messageListConfiguration = new MessageListConfiguration({
  templates: getTemplates(),
  headerView: <div></div>, // Optional if you want a static header
});

<CometChatMessages
  user={user}
  group={group}
  messageHeaderView={(user: any, group: any) => getHeaderView(user, group)}
  messageListConfiguration={messageListConfiguration}
/>