Mention in Messages

The mention feature in chat can be used to call attention to specific members. By @mentioning their names, this will promptly notify them so you can get a faster response to your message.

You can mention members or a channel in text messages. Just specify the display name to mention. Up to 30 channel members can be mentioned per message.

You can fetch mention configurations and provide information about unread text messages with mention.

Mention is supported in these channel types:

  • Community

  • Live

Mention is not supported in the Conversation channel type.

AmityMessage contains new properties related to mention feature:

  • mentionedUsers - an array of AmityUser objects. It provides information of mentioned users in the current text message.

  • metadata - a dictionary which can contain any information about the current message. Our default structure to represent mentions is inside the metadata property. Customers can use any structure to represent mentions. AmityMessageMentionMetadatais a helper class which can transform metadata into mentions and vice versa. This class uses our custom structure of representing mentions in text messages.

  • mentionees - an array of AmityMentionees objects. AmityMentionees model represents the following information about mentions in the message:

    • type: AmityMessageMentionType. The type of the current mention. This can either be user or channel.

    • users: Nullable array of AmityUser. The users list who are mentioned in the current message. If AmityMessageMentionType is channel, this array will be empty.

The mentionees array can contain a maximum of two objects because mention type can be only eitherchannel or user. Each object in the array represents information about a specific type of mention.

How mention works

You can define your own structure to represent mentions. To do this, you can use the metadata property of AmityMessage and store mentions in the metadata property. To represent mentions with our own structure, you need to use the AmityMessageMentionMetadata helper class and AmityMention class.

AmityMessageMentionMetadata has two class member functions:

Member function

Description

func mentions(fromMetadata metadata: [String : Any]) -> [AmityMention]

Takes metadata dictionary as an argument and if it’s possible, then it gets mentions from metadata and returns an array of AmityMention.

func metadata(from mentions: [AmityMention]) -> [String : Any]

Takes an array of AmityMention and creates a metadata dictionary. This method helps to create text messages with mentions.

How to use AmityMention

To represent mention with our structure, you must use the AmityMention model array provided by AmityMessageMentionMetadata’s mentionsFromMetadata method.

AmityMention model contains four properties:

  • type: AmityMessageMentionType - type of the mention

  • index: Integer - start index of current mention

  • userId: String - userId of the user being mentioned. If the type of the mention is channel, then userId is undefined.

  • length: Integer - length of the mention

The length property doesn’t include the “@“ mention sign. For example, “@all” mention’s length is 3.

func updateTextLabel(from message: AmityMessage) {
    guard let metadata = message.metadata,
          let textMessage = message.data?["text"] as? String else {
        return
    }
    
    let mentions = AmityMentionMapper.mentions(fromMetadata: metadata)
    let attributedString = NSMutableAttributedString(string: textMessage)
    for mention in mentions {
          let range = NSRange(location: mention.index, length: mention.length + 1)
          if range.location != NSNotFound && range.location + range.length <= textMessage.count {
               attributedString.addAttribute(.foregroundColor, value: UIColor.green, range: range)
          }
    }
    
    // Set the attributed string to your label.
    messageLabel.attributedText = attributedString
}

How to create a mention with our structure

We create mentions in metadata to be able to represent mentions on different platforms(iOS, Android, and Web). Back-end won’t validate metadata property for message, but we need to provide amentionees object to Back-end to be able to handle notifications.

AmityMentioneesBuilder class helps build mentionees object. It has two methods:

  • mentionChannel() - builds mention with channel

  • mentionUsers(userIds: [String]) - takes an array of userIds and builds mentions with type user and userIds

To create a text message with mentions, there is a new method in AmityMessageRepository:

func createTextMessage(channelId:text:tags:parentId:metadata:mentionees:completion:) -> String

To update a text message and provide mention information, there is a new method in AmityMessageEditor:

func editText(_:metadata:mentionees:completion:)

Create metadata and mentionees objects. Send a text message with mentions.

let messageRepository = AmityMessageRepository(client: client)

...

func createMessageAndMentionUserExample() {
    // A sample message.
    let textMessage = "Hi @John Doe"
    
    // Range 3 to 11 is "@John Doe".
    let userMention = AmityMention(type: .user, index: 3, length: 11, userId: "johndoe145")
    
    let metadata = AmityMentionMapper.metadata(from: [userMention])
    
    let mentionees: AmityMentioneesBuilder = AmityMentioneesBuilder()
    mentionees.mentionUsers(userIds: ["johndoe145"])
    
    messageRepository.createTextMessage(channelId: "channelId", text: textMessage, tags: nil, parentId: nil, metadata:
metadata, mentionees: mentionees) { message, error in
        // Handle message creation result.
    }
    
}

func createMessageAndMentionChannelExample() {
    // A sample message.
    let textMessage = "Good morning @all"

    // A string at index 13 with length 4 is "@all".
    let channelMention = AmityMention(type: .channel, index: 13, length: 4, userId: nil)
    let metadata = AmityMentionMapper.metadata(from: [channelMention])
    
    // With a channel-type mention, it will notify everyone in the channel.
    // And it doesn't require a `userId`.
    let mentionees: AmityMentioneesBuilder = AmityMentioneesBuilder()
    mentionees.mentionChannel()
    messageRepository.createTextMessage(channelId: "channelId", text: textMessage, tags: nil, parentId: nil, metadata:
    metadata, mentionees: mentionees) { message, error in
        // Handle message creation result.
    }
}

How to update mentions for a text message

func editMessageAndMentionUserExample(from message: AmityMessage) {
    // A sample message.
    let editedMessage = "See you @John Doe"
    
    // A string at index 8 with length 8 is "@John Doe".
    let userMention = AmityMention(type: .user, index: 8, length: 8, userId: "johndoe145")
    
    let metadata = AmityMentionMapper.metadata(from: [userMention])
    let mentionees: AmityMentioneesBuilder = AmityMentioneesBuilder()
    mentionees.mentionUsers(userIds: ["johndoe145"])
    
    let editor = AmityMessageEditor(client: client, messageId: message.messageId)
    editor.editText(editedMessage, metadata: metadata, mentionees: mentionees) { success, error in
        // Handle success and error.
    }
}

Mention Configurations

Mention channel can be turned off. It means that you cannot mention that specific channel. To get configurations for mention channel, you must use AmityClient’s mentionConfigurations property which is the AmityMentionConfigurations object.

AmityMentionConfigurations has the isMentionAllEnabled property which is an indicator whether you can mention the channel or not.

Search members

To search members when mentioning, you must use AmityChannelParticipation’s searchMembers function:

func searchMembers(displayName:filterBuilder:roles:) -> AmityCollection<AmityChannelMember>

The above function takes the following parameters to make a search:

  • searchMembers - display name or user ID of the member being searched

  • filterBuilder - to help build a filter for filtering search results

  • roles

It will return AmityCollection of AmityChannelMember.

You can filter search results with more than one option. For example, filter by muted and banned users. AmityChannelMembershipFilterBuilder has this method:

func add(filter:)

This function takes the AmityChannelMembershipSearchFilter type as an argument. Search results are ordered by last created.

AmityChannelMembershipSearchFilter is an enum which has three cases:

  • member - Standard member

  • mute - Muted member

  • ban - Banned member

Usage:

var token: AmityNotificationToken?
let participation = AmityChannelParticipation(client: client, andChannel: "channelId")

... 

func searchMutedAndBannedMembersExample() {
    let filterBuilder = AmityChannelMembershipFilterBuilder()
    filterBuilder.add(filter: .mute)
    filterBuilder.add(filter: .ban)

    token = participation.searchMembers(displayName: "John Doe", filterBuilder: filterBuilder, roles: []).observe
    { collection, change, error in
        for member in collection.allObjects() {
            // For example, to handle each member in the list.
        }
    }
}

This code will return AmityCollection of AmityChannelMember which contains only banned and muted users.

Unread mention count

When a member is mentioned(mention type could be channel as well) in a text message and the message is not read, then hasMention property is "true" in AmityChannel class. Everytime the hasMention property is true, this means that the member has an unread message with mention(message could be created or updated as well).

Mentioning banned users

Banned users cannot be mentioned. However, admins can still find the banned users' names in the suggestion list during search when composing the message. But once the message is sent, the banned users’ information will not be included in the message payload anymore.

Banned users will not be notified nor receive any push notification.

Users who are not admins will not be able to search for the banned users' names as the latter will not appear in the suggestion list.

Mention notifications

When users are being mentioned, they will receive push notifications. You can customize the push notification content such as the title and the body using the notification setting API.

Provide the notification title and body in the titleTemplate and bodyTemplate parameters respectively. Here is a sample model:

{
  "level": "network",
  "isPushNotifiable": true,
  "notifiableEvents": [
   {
      "name": "text-mention-message.created",
      "isPushNotifiable": true,
      "titleTemplate": "{{UserDisplayName}} mentioned you in {{ChannelName}}",
      "bodyTemplate": "{{Message}}"
    }
  ]
}

NameData TypeDescription

name

String

Event name

isPushNotifiable

Boolean

If set to true,push notification will be received for all text messages. If set to false, only messages with mention will have push notifications.

titleTemplate

String

Notification title

bodyTemplate

String

Notification body

Last updated