Observe threads

Build thread previews with detailed data about all threads visible to the current user


Overview #

This API allows you to observe threads data within your application, that are visible to the current user, including live updates. You can use the available filter options to fine tune the threads returned.
React:
import { thread } from '@cord-sdk/react';
const { threads, loading, hasMore, fetchMore, counts } = thread.useThreads({
  sortBy: 'first_message_timestamp',
  filter: {
    location: {
      value: { page: 'document_details' },
      partialMatch: true
    },
    metadata: { category: 'sales' },
  },
});

return (
  <div>
     {counts &&
        <div>
          We have {counts.total} total threads and {counts.unread} unread threads.
        </div>
      }
    {threads.map((thread) => (
      <div key={thread.id}>
        Thread ID {thread.id} has {thread.total} messages!
      </div>
    ))}
    {loading ? (
      <div>Loading...</div>
    ) : hasMore ? (
      <div onClick={() => fetchMore(10)}>Fetch 10 more</div>
    ) : null}
  </div>
);
Vanilla JavaScript:
const ref = window.CordSDK.thread.observeThreads(
  ({ threads, loading, hasMore, fetchMore, counts }) => {
    console.log('Got a thread data update:');
    if (loading) {
      console.log('Loading...');
    }
     if (counts){
      console.log(`Total threads: ${counts.total} and unread threads: ${counts.unread}`)
     }
    threads.forEach((thread) =>
      console.log(\`Thread \${thread.id} has \${thread.total} messages!\`)
    );
    if (!loading && hasMore && threads.length < 25) {
      // Get the first 25 threads, 10 at a time.
      fetchMore(10);
    }
  },
  { filter: {
       location: {
             'value': { 'page': 'document_details'},
             'partialMatch': true
            },
       metadata: {'category': 'sales'}
   }}
);
// ... Later, when updates are no longer needed ...
window.CordSDK.thread.unobserveThreads(ref);
import { thread } from '@cord-sdk/react';
const { threads, loading, hasMore, fetchMore, counts } = thread.useThreads({
  sortBy: 'first_message_timestamp',
  filter: {
    location: {
      value: { page: 'document_details' },
      partialMatch: true
    },
    metadata: { category: 'sales' },
  },
});

return (
  <div>
     {counts &&
        <div>
          We have {counts.total} total threads and {counts.unread} unread threads.
        </div>
      }
    {threads.map((thread) => (
      <div key={thread.id}>
        Thread ID {thread.id} has {thread.total} messages!
      </div>
    ))}
    {loading ? (
      <div>Loading...</div>
    ) : hasMore ? (
      <div onClick={() => fetchMore(10)}>Fetch 10 more</div>
    ) : null}
  </div>
);
Copy

Available Data #

The API provides an object which has the following fields:


loading #

boolean
When this is true, Cord is in the process of fetching additional data from its backend. Once the fetch is complete, the additional items will be appended to the result list, and loading will become false.
Both the initial data load and a call to fetchMore will start a fetch and cause loading to become true.

fetchMore #

FetchMoreCallback
Call this function to fetch additional data from Cord's backend. It takes a single argument, the number of additional items to fetch.
Once called, loading will become true while the data is fetched. Once the fetch is complete, the additional items will be appended to the result list, and loading will return to false.
This function returns a promise that is resolved once the fetch is complete.

hasMore #

boolean
If this is true, then the list of results is incomplete, and you need to call fetchMore to continue paginating through them. Once this becomes false, all results are available, and calls to fetchMore won't do anything.

threads #

ThreadSummary[]
An array of objects containing the threads that match the request.
This array is paginated. At first, it will contain only the first few threads. Calling fetchMore will cause further threads to be appended to the array.
The order in which you will receive the threads is determined by the sorting options.

This is an array of objects, each of which has the following fields:


unread #

number
The number of messages that the current user hasn't seen yet. This count excludes deleted messages.

viewerIsThreadParticipant #

boolean
Whether the current viewer has either left a message or reacted to this thread.

firstMessage #

ClientMessageData | null
Contains information about the first (i.e., oldest) message in the thread. null if the thread is empty.

This is an object with the following fields:


seen
boolean
Whether the message has been seen by the current viewer.

id
string
The ID for the message. If a message is created with no ID, a random UUID-based ID will be automatically created for it.

authorID
string
The ID for the user that sent the message.

groupID
string
The ID for the group this message belongs to.

threadID
string
The ID for the thread this message is part of.

content
object[]
The content of the message.

plaintext
string
A plaintext version of the structured message content.

url
string | null
A URL where the message can be seen. This determines where a user is sent when they click on a reference to this message, such as in a notification. If unset, it defaults to the thread's URL.

createdTimestamp
Date
The timestamp when this message was created. The default value is the current time.

deletedTimestamp
Date | null
The timestamp when this message was deleted, if it was. If unset, the message is not deleted.

updatedTimestamp
Date | null
The timestamp when this message was last edited, if it ever was. If unset, the message does not show as edited.

iconURL
string | null
The URL of the icon to show next to the message. This is only used for action_message messages; other messages show the avatar of the author. If an action_message does not have an icon set, no icon is shown.

translationKey
string | null
An optional translation key used for this message. This is useful for system-generated messages where you might want to translate or customize them at runtime. See the translations documentation for more information.

type
"action_message" | "user_message"
The type of message this is. A user_message is a message that the author sent. An action_message is a message about something that happened, such as the thread being resolved. The default value is user_message.

metadata
EntityMetadata
Arbitrary key-value pairs that can be used to store additional information.

extraClassnames
string | null
A optional space separated list of classnames to add to the message.

attachments
array
The items attached to this message.

reactions
Reaction[]
The reactions to this message.

This is an array of objects, each of which has the following fields:


reaction
string
The emoji reaction.

userID
string
The ID of the user who reacted to the message.

timestamp
Date
The timestamp of when the reaction was created.

seenBy
string[]
A list of IDs of the users that have seen the message.

skipLinkPreviews
boolean
If set, Cord won't analyze links in the message to generate previews.

lastMessage #

ClientMessageData | null
Contains information about the last (i.e., newest) message in the thread. null if the thread is empty.

This is an object with the following fields:


seen
boolean
Whether the message has been seen by the current viewer.

id
string
The ID for the message. If a message is created with no ID, a random UUID-based ID will be automatically created for it.

authorID
string
The ID for the user that sent the message.

groupID
string
The ID for the group this message belongs to.

threadID
string
The ID for the thread this message is part of.

content
object[]
The content of the message.

plaintext
string
A plaintext version of the structured message content.

url
string | null
A URL where the message can be seen. This determines where a user is sent when they click on a reference to this message, such as in a notification. If unset, it defaults to the thread's URL.

createdTimestamp
Date
The timestamp when this message was created. The default value is the current time.

deletedTimestamp
Date | null
The timestamp when this message was deleted, if it was. If unset, the message is not deleted.

updatedTimestamp
Date | null
The timestamp when this message was last edited, if it ever was. If unset, the message does not show as edited.

iconURL
string | null
The URL of the icon to show next to the message. This is only used for action_message messages; other messages show the avatar of the author. If an action_message does not have an icon set, no icon is shown.

translationKey
string | null
An optional translation key used for this message. This is useful for system-generated messages where you might want to translate or customize them at runtime. See the translations documentation for more information.

type
"action_message" | "user_message"
The type of message this is. A user_message is a message that the author sent. An action_message is a message about something that happened, such as the thread being resolved. The default value is user_message.

metadata
EntityMetadata
Arbitrary key-value pairs that can be used to store additional information.

extraClassnames
string | null
A optional space separated list of classnames to add to the message.

attachments
array
The items attached to this message.

reactions
Reaction[]
The reactions to this message.

This is an array of objects, each of which has the following fields:


reaction
string
The emoji reaction.

userID
string
The ID of the user who reacted to the message.

timestamp
Date
The timestamp of when the reaction was created.

seenBy
string[]
A list of IDs of the users that have seen the message.

skipLinkPreviews
boolean
If set, Cord won't analyze links in the message to generate previews.

id #

string
The ID for this thread.

groupID #

string
The group ID this thread is in.

total #

number
The total number of messages in this thread. Equal to user messages + action messages. Deleted messages are excluded from this count.

userMessages #

number
The number of messages in this thread that were sent by users (i.e., not action messages).

actionMessages #

number
The number of action messages sent in this thread. An example is the message that appears when a thread is resolved.

deletedMessages #

number
The number of deleted messages in this thread.

resolved #

boolean
Whether this thread is resolved. This is equivalent to checking if resolvedTimestamp is null.

resolvedTimestamp #

Date | null
The timestamp when this thread was resolved. Set to null if this thread is not resolved.

participants #

ThreadParticipant[]
All of the users who are engaging in this thread. This includes both subscribed and unsubscribed users.

This is an array of objects, each of which has the following fields:


lastSeenTimestamp
Date | null
The timestamp of the most recent message or reaction that this user has seen in this thread. Is null if this participant has never viewed this thread.

userID
string | null
The user ID of the participant. Can be null if the current viewer no longer shares a group with this participant (and therefore can no longer access that participant's information).

subscribers #

string[]
All of the users who are subscribed to this thread.

repliers #

string[]
All of the users who have replied to this thread.

typing #

string[]
The users that are currently typing in this thread. Typing status is transient in nature, so the value is the set of users typing at a particular instant, but may change rapidly.

name #

string
The name of the thread. This is shown to users when the thread is referenced, such as in notifications. This should generally be something like the page title.

url #

string
A URL where the thread can be seen. This determines where a user is sent when they click on a reference to this thread, such as in a notification, or if they click on a reference to a message in the thread and the message doesn't have its own URL.

location #

Location
The location of this thread.

metadata #

EntityMetadata
Arbitrary key-value pairs that can be used to store additional information.

extraClassnames #

string | null
An optional space separated list of classnames to add to the thread.

counts #

ThreadActivitySummary
An object providing counts of threads. Refer to observeThreadCount API for more information about the properties returned.

This is an object with the following fields:


total #

number
The total number of threads, both resolved and unresolved. This does not include threads in which all messages have been deleted.

unread #

number
The total number of threads that contain at least one unread message in the thread.
This will count all threads with unread messages, whether the current user is subscribed to the thread or not.

unreadSubscribed #

number
The number of threads that have messages the current user hasn't seen yet and is subscribed to.
A user is automatically subscribed to threads relevant to them, for example because they have sent a message or have been @-mentioned in them. unreadSubscribed is always less than or equal to unread.

new #

number
The total number of threads that the user has never seen before at all, i.e., every message in the thread is unread.
This will count all threads with unread messages, whether the current user is subscribed to the thread or not.

resolved #

number
The number of resolved threads. This refers to threads that users have manually marked as resolved within Cord's UI components.

empty #

number
The number of thread with no visible messages. This refers to threads in which all the messages have been deleted.

What this function returns #

The hook will return an object containing the fields described under "Available Data" above. The component will automatically re-render if any of the data changes, i.e., this data is always "live".

Arguments this function takes #


options #

optional
ObserveThreadsOptions
Options that control which threads are returned.

This is an object with the following fields:


sortBy #

optional
"first_message_timestamp" | "most_recent_message_timestamp"
This option controls the criteria for how threads are sorted. Combined with sortDirection, it determines which threads are "first".
It's a string enum which can have one of the following values:
  • first_message_timestamp: sort threads by the timestamp of the first message in the thread. In other words, threads will be sorted based on how recently they were created.
  • most_recent_message_timestamp: sort threads by the timestamp of the most recent message in the thread. In other words, threads will be sorted based on how recently they were responded to.
If unset, defaults to first_message_timestamp.

sortDirection #

optional
"ascending" | "descending"
This option controls the direction that sortBy sorts. Combined with sortBy, it determines which threads are "first".
It's a string enum which can have one of the following values:
  • ascending: sort older threads in front of newer threads.
  • descending: sort newer threads in front of older threads.
If unset, defaults to descending (since people usually care about the most recent things).

filter #

optional
ClientThreadFilter
An object that can be used to filter the threads returned.

This is an object with the following fields:


location
optional
The Location of the threads. This can either be just the location value or an object with a value for both the location and partialMatch properties.
The value for partialMatch will default to false if only location is provided.

This property can be one of the following:

  • Location
  • LocationFilterOptions

    This is an object with the following fields:


    value
    Location
    The Location of the threads.

    partialMatch
    boolean
    If true, perform partial matching on the specified location. If false, fetch information for only exactly the location specified.

resolvedStatus
optional
"resolved" | "any" | "unresolved"
If set to resolved, only resolved threads will be returned. If set to unresolved, only unresolved threads will be returned. If set to any, both resolved and unresolved threads will be returned.
If unset, defaults to any.

metadata
optional
EntityMetadata
The value for a metadata entry should be an object representing the metadata key/value to filter on. For example, to show only threads with the metadata key of "category" set to "sales", set the filter to { metadata: { category: "sales" } }.

Ask Cordy