Data components for PubNub Chat Components for Android
Data components are responsible for managing data between the UI Components and the persistence layer. They also interact with the PubNub service by sending and receiving messages and signals.
Available components include:
Overview
PubNub Chat Components for Android utilize several layers of configurable data to drive the functionality found in the UI Components. The goal of the data layer is to provide a simple and robust foundation that can be used across any chat implementation. The two main forms of data used by the components are persistent and network objects.
Persistent data
All the data is stored as entities in a local database using Room, an abstraction layer over SQLite. Room provides the following benefits:
- Compile-time verification of SQL queries.
- Convenience annotations that minimize repetitive and error-prone boilerplate code.
- Streamlined database migration paths.
You can find the default implementation of the database in ChatProvider. It contains data entities, data access objects, and database implementation. Additionally, ChatProvider uses the repository design pattern that allows for separation of concerns by abstracting the data persistence logic.
To learn more about Room, refer to the official Android docs.
Network data
Network objects are most commonly used when interacting with PubNub APIs. Those objects exist only at the network layer and need to be converted with Data Mappers to be used in the application.
UI data
The UI Components don't use persistent or network data but extra UI data objects are created for them instead. These UI data objects contain only user-readable information. For example, to display a timetoken, it must be converted to a date string first.
Data mappers
The role of Data Mappers is to convert one data type to another to allow developers to swap between Persistent, Network, and UI data objects. For example, when the NetworkMessage is received by MessageService, the data is converted to DBMessage and stored in the database. Similarly to the previous example, when the user sends a message, the MessageUi.Data object is converted to DBMessage and stored in the local database. At the same time, the object is converted to NetworkMessagePayload and published in PubNub.
View models
The ViewModel class is designed to store and manage UI-related data by communicating with services and repositories.
For more information on view models, refer to the official Android docs.
Services
The role of services is to communicate with PubNub APIs, add, get, or update objects and store them using local repositories. The default implementation of services exists in the ChatProvider composition tree.
Data flow
The typical data flow through the components revolves around storing incoming data in the Room database instance and updating that data automatically in UI Components if the data matches the UI Components population query.

-
The PubNub APIs and events return network data that can be stored directly in the Room database using the repositories declared in
ChatProvider. -
The UI Components use specific view models to connect with the database (persistent data) through repositories and Data Access Object instances. If the returned type of the
ViewModelmethod is declared asFlow, it automatically updates the component's data source if the new matching data is added, updated, or removed. -
The UI Components provide actions that can be configured to call PubNub APIs through
DataProvideror update existing objects and store the result.
Data payloads
PubNub Chat Components for Android enforce you to use the unified JSON schemas (data models) for such common entity types as users, channels, and messages when transferring data over the PubNub network. These common data payloads allow you to create cross-platform applications and ensure that such applications developed in different technologies (Swift, Kotlin, or JavaScript) communicate with one another properly, avoiding any unexpected errors.
Validate your payload
To avoid any parsing errors, validate the data payload you prepared for users, channels, and messages in an online validator.
Users
Follow this schema for the user data in your apps:
1{
2 "$schema": "https://json-schema.org/draft/2020-12/schema",
3 "title": "User",
4 "type": "object",
5 "description": "User of a chat application",
6 "properties": {
7 "id": {
8 "description": "Unique identifier for a user",
9 "type": "string"
10 },
11 "name": {
12 "description": "Name of the user that you can display in the UI",
13 "type": "string"
14 },
15 "email": {
show all 58 linesExample:
1{
2 "id": "some-user-id",
3 "name": "Jane Doe",
4 "email": "jane.doe@example.com",
5 "externalId": "some-external-user-id",
6 "profileUrl": "https://randomuser.me/api/portraits/men/1.jpg",
7 "type": "default",
8 "status": "default",
9 "custom": {
10 "description": "Office Assistant",
11 },
12 "eTag": "AYGyoY3gre71eA",
13 "updated": "2020-09-23T09:23:34.598494Z"
14}
Channels
Follow this schema for the channel data in your apps:
1{
2 "$schema": "https://json-schema.org/draft/2020-12/schema",
3 "title": "Channel",
4 "description": "Channel in the chat application",
5 "type": "object",
6 "properties": {
7 "id": {
8 "description": "Unique identifier for a channel",
9 "type": "string"
10 },
11 "name": {
12 "description": "Name of the channel that you can display in the UI",
13 "type": "string"
14 },
15 "description": {
show all 50 linesExample:
1{
2 "id": "some-channel-id",
3 "name": "Off-topic",
4 "description": "Off-topic channel for random chatter and fun",
5 "type": "default",
6 "status": "default",
7 "custom": {
8 "profileUrl": "https://www.gravatar.com/avatar/149e60f311749f2a7c6515f7b34?s=256&d=identicon"
9 },
10 "eTag": "AbOx6N+6vu3zoAE",
11 "updated": "2020-09-23T09:23:37.175764Z"
12}
Messages
Follow this schema for the message data in your apps:
Supported message types
PubNub Chat Components for Android support only text message data types.
1{
2 "$schema": "https://json-schema.org/draft/2020-12/schema",
3 "title": "Message Content",
4 "description": "Message content in the chat application",
5 "type": "object",
6 "properties": {
7 "id": {
8 "description": "Unique identifier for a message. Use the UUID v4 algorithm.",
9 "type": "string"
10 },
11 "text": {
12 "description": "Text of the message that you can display in the UI",
13 "type": "string"
14 },
15 "contentType": {
show all 34 linesExample:
1{
2 "id": "6da72b98-e211-4724-aad4-e0fb9f08999f",
3 "text": "Let's sync on the topic in this thread.",
4 "contentType": "none",
5 "content": {},
6 "custom": {},
7 "createdAt": "2022-05-10T14:48:00.000Z"
8}
Channel
A channel is commonly viewed as a collection of associated users with a specific purpose or goal. A channel could be created for direct communication between two or more users, a group of users, or other use case-specific scenarios.
Persistent data
The default Persistent Object Model inside the Chat Components defines an Entity named DBChannel.
If a custom Persistent Object Model is used, then an Entity must implement the Channel interface before it can be used by the Chat Components framework.
To return all the members from a selected channel, the DBChannelWithMembers object is implemented.
Default channel entity
The DBChannel entity is defined with the following attributes:
| Name | Type | Description |
|---|---|---|
id | ChannelId | Unique identifier for the object. Used as a primary key. |
name | String? | Name of the channel that can be displayed in the UI. |
description | String? | Channel details that can be displayed alongside the name. |
type | String | Functional type of the channel. The default value is set to "default". |
status | String? | Status of the channel. |
custom | Any? | Any additional custom payload (as a key-value pair) that can be stored with the channel. |
profileUrl | String? | URL to an image that can be used to visually represent the channel. |
eTag | String? | Caching value that changes whenever the remote object changes. It isn't used in PubNub Chat Components for Android. |
updated | String? | Last time the remote object was changed. It isn't used in PubNub Chat Components for Android. |
The CustomDataMap typealias is a map which stores additional key-value properties.
1typealias CustomDataMap = HashMap<String, Any>
Custom channel entity
To create a custom Persistent Object Model, you must implement the Channel interface.
The following properties are required:
1interface Channel {
2 val id: ChannelId
3 val name: String?
4 val description: String?
5 val type: String
6 val status: String?
7 val custom: Any?
8 val profileUrl: String?
9 val eTag: String?
10 val updated: String?
11}
Relationships
The DBChannelWithMembers entity contains the following attributes:
| Name | Type | Description |
|---|---|---|
channel | DBChannel | Entity of the channel object. |
members | List<DBMember> | List of members with membership in a selected channel. |
Repository
PubNub Chat Components for Android use a default channel repository named DefaultChannelRepository.
If you want to use a custom Persistent Object Model, create a custom ViewModel in which your Repository implements the ChannelRepository interface before it can be used by the Chat Components framework.
Default channel repository
The DefaultChannelRepository implementation is defined with the following attributes:
| Name | Type | Description |
|---|---|---|
channelDao | ChannelDao<DBChannel, DBChannelWithMembers> | Room's data access object (DAO) for the channel entity. |
The ChannelDao interface uses both DBChannel and DBChannelWithMembers types. The first one is used for CRUD operations (Create, Read, Update, Delete) and the second one defines the type of the returned object.
Custom channel repository
To create a custom channel repository, implement the ChannelRepository interface.
These are the required methods:
-
get()Used to get one
Channelobject with specifiedidfrom the database. It returnsnullwhen the object doesn't exist.1suspend fun get(id: ChannelId): OUT? -
getAll()Returns the paginated source of channels.
1fun getAll(
2 id: UserId? = null,
3 filter: Query? = null,
4 vararg sorted: Sorted = emptyArray(),
5): PagingSource<Int, OUT>Name Type Description idUserId?If specified, this method returns only channels the user is a member of. filterQuery?Query filter for the database. sortedSortedArray of sorted keys and directions. Example:
1val repository: DefaultChannelRepository = LocalChannelRepository.current
2
3val channels = remember {
4 repository.getAll(
5 id = "my-user-id",
6 filter = Query("type LIKE ?", "group"),
7 sorted = arrayOf(Sorted("type", Sorted.Direction.ASC)),
8 )
9} -
getList()Returns the list of all channels.
1suspend fun getList(): List<OUT> -
insertOrUpdate()Sets or updates a channel object in the database.
1suspend fun insertOrUpdate(vararg channel: IN) -
remove()Removes the channel object with the specified ID.
1suspend fun remove(id: ChannelId) -
size()Returns the number of all channels.
1suspend fun size(): Long
Network data
The NetworkChannelMetadata class is used to communicate with PubNub APIs to send and receive channel metadata.
| Name | Type | Description |
|---|---|---|
id | String | Unique identifier for the object. |
name | String? | Name of the channel. |
description | String? | Channel details that can be displayed alongside the name. |
type | String | Functional type of the channel. The default value is set to "default". |
status | String? | Status of the channel. |
custom | Any? | Custom key value pairs that can be stored with the channel. |
profileUrl | String? | URL to an image that can be used to visually represent the channel. |
eTag | String? | Caching value that changes whenever the remote object changes. It isn't used in PubNub Chat Components for Android. |
updated | String? | Last time the remote object was changed. It isn't used in PubNub Chat Components for Android. |
Custom channel data
NetworkChannelMetadata contains the custom property. You can use it to store a custom object. In the default implementation, NetworkChannelMapper is implemented to parse the custom object to CustomDataMap.
Service
PubNub Chat Components for Android use a default service named DefaultChannelServiceImpl. This service is responsible for synchronizing PubNub APIs network channel data and storing it in the local database.
You can obtain the instance or override it using LocalChannelService in CompositionLocalProvider. If you want to use a custom service, you need to create a class that implements the ChannelService interface.
Default channel service
The DefaultChannelService implementation is defined with the following attributes:
| Name | Type | Description |
|---|---|---|
pubNub | PubNub | PubNub instance. |
logger | Logger | Instance of the logging class. |
Custom channel service
To create a custom channel service, implement the ChannelService interface and pass it as a parameter to the composition tree. You can do it by wrapping ChatProvider with CompositionLocalProvider.
1CompositionLocalProvider(LocalChannelService provides MyChannelServiceImpl){
2 ChatProvider(…)
3}
These are the required methods:
-
bind()Subscribes to the channels and sets listeners for channel events.
1fun bind(vararg channels: String) -
unbind()Removes the listeners and unsubscribes from channels.
1fun unbind()
Member
The users that are associated with a channel are also known as its members. A user might have many channel memberships and a channel might have multiple members.
Persistent data
The default Persistent Object Model inside the Chat Components defines an Entity named DBMember.
If a custom Persistent Object Model is used, then an Entity must implement the Member interface before it can be used by the Chat Components framework.
Default member entity
The DBMember entity is defined with the following attributes:
| Name | Type | Description |
|---|---|---|
id | UserId | A unique identifier for the object. Used as a primary key. |
name | String | Name of the user. |
email | String? | Email address of the user. It isn't used in PubNub Chat Components for Android. |
externalId | String? | A unique external identifier for the user. It isn't used in PubNub Chat Components for Android. |
profileUrl | String? | Image that can be used to visually represent the user. |
type | String | Functional type of the user. The default value is set to "default". |
status | String? | Status of the user. |
custom | Any? | Custom object to store a description of the user. |
eTag | String? | Caching value that changes whenever the remote object changes. It isn't used in PubNub Chat Components for Android. |
updated | String? | Last time the remote object was changed. It isn't used in PubNub Chat Components for Android. |
Custom member entity
To create a custom Persistent Object Model, you must implement the Member interface.
The following properties are required:
1interface Member {
2 val id: UserId
3 val name: String
4 val email: String?
5 val externalId: String?
6 val profileUrl: String?
7 val type: String
8 val status: String?
9 val custom: Any?
10 val eTag: String?
11 val updated: String?
12}
Relationships
The DBMemberWithChannels entity contains the following attributes:
| Name | Type | Description |
|---|---|---|
member | DBMember | Entity of a member object. |
channels | List<DBChannel> | List of channels with membership. |
Repository
PubNub Chat Components for Android use a default member repository named DefaultMemberRepository.
If a custom Persistent Object Model is used, then a Repository must implement the MemberRepository interface before it can be used by the Chat Components framework. Also, you must implement a custom view model.
Default member repository
The DefaultMemberRepository implementation is defined with the following attributes:
| Name | Type | Description |
|---|---|---|
memberDao | MemberDao<DBMember, DBMemberWithChannels> | Room DAO for the member entity. |
The MemberDao interface uses both DBMember and DBMemberWithChannels types. The first one is used for CRUD operations (Create, Read, Update, Delete) and the second one defines the type of the returned object.
Custom member repository
To create a custom member repository, you must implement a MemberRepository interface.
The following methods are required:
-
get()Used to get one member object with specified
idfrom the database. Returnsnullwhen the object doesn't exist.1suspend fun get(id: UserId): OUT? -
getAll()Returns paginated source of members. Possible arguments are:
1fun getAll(
2 id: ChannelId? = null,
3 filter: Query? = null,
4 vararg sorted: Sorted = emptyArray(),
5): PagingSource<Int, OUT>Name Type Description idChannelId?If specified, returns all members of the channel with the specified ID. filterQuery?Query filter for the database. sortedSortedArray of sorted keys and directions. Example:
1val repository: DefaultMemberRepository = LocalMemberRepository.current
2
3val members = remember {
4 repository.getAll(
5 id = "channel-id",
6 filter = Query("name LIKE ?", "Android"),
7 sorted = arrayOf(Sorted("name", Sorted.Direction.ASC)),
8 )
9} -
getList()If
idis specified, it returns the list of members of the specified channel. Otherwise, it returns the list of all members.1suspend fun getList(id: ChannelId? = null): List<OUT> -
insertOrUpdate()Sets or updates a member object in the database.
1suspend fun insertOrUpdate(vararg member: IN) -
remove()Removes the member object with the specified ID.
1suspend fun remove(id: UserId) -
size()Returns the number of all members.
1suspend fun size(): Long
Network data
The NetworkMember class is used to communicate with PubNub APIs to send and receive user metadata.
| Name | Type | Description |
|---|---|---|
id | UserId | A unique identifier for the object. Used as a primary key. |
name | String | Name of the user. |
email | String? | Email address of the user. It isn't used in PubNub Chat Components for Android. |
externalId | String? | A unique external identifier for the user. It isn't used in PubNub Chat Components for Android. |
profileUrl | String? | Image that can be used to visually represent the user. |
type | String | Functional type of the user. The default value is set to "default". |
status | String? | Status of the user. |
custom | Any? | Custom object to store a description of the user. |
eTag | String? | Caching value that changes whenever the remote object changes. It isn't used in PubNub Chat Components for Android. |
updated | String? | Last time the remote object was changed. It isn't used in PubNub Chat Components for Android. |
Custom member data
The NetworkMember contains the custom property. You can use it to store a custom object.
Message
A message is the dynamic content that a user sends to other users inside a channel.
Persistent data
The default Persistent Object Model inside the Chat Components defines an Entity named DBMessage.
If a custom Persistent Object Model is used, then an Entity must implement the Message interface before it can be used by the Chat Components framework.
Default message entity
The DBMessage entity is defined with the following attributes:
| Name | Type | Description |
|---|---|---|
id | String | Unique identifier for the object. Used as a primary key. |
text | String | Text of the message. |
contentType | String? | If a message contains any extra content, this field describes its type. Currently, PubNub Chat Components support only text messages. |
content | Any? | Extra content for the message like feature-specific data like URLs to external images. |
createdAt | String | ISO8601 date string of when the message was created. |
custom | Any? | Custom key value pairs that can be stored with the message. |
publisher | UserId | ID of the message publisher. |
channel | ChannelId | ID of the channel the message is published on. |
timetoken | Timetoken | Time when a message was created. |
published | Timetoken | Time when a message was published. |
isSent | Boolean | Information if a message was sent successfully. |
exception | String? | Error details when an exception is thrown. |
Custom message entity
To create a custom Persistent Object Model, you must implement the Message interface.
The following properties are required:
1interface Message {
2 val id: MessageId
3 val text: String
4 val contentType: String?
5 val content: Any?
6 val createdAt: String
7 val custom: Any?
8}
Repository
PubNub Chat Components for Android use a default message repository named DefaultMessageRepository.
If you want to use a custom Persistent Object Model, a Repository must implement the MessageRepository interface before it can be used by the Chat Components framework. Also, you must implement a custom view model.
Default message repository
The DefaultMessageRepository implementation is defined with the following attributes:
| Name | Type | Description |
|---|---|---|
messageDao | MessageDao<DBMessage, DBMessage> | Room DAO for the message entity. |
The MessageDao interface uses the DBMessage type for CRUD operations (Create, Read, Update, Delete) and to define the type of the returned object.
Custom message repository
To create a custom message repository, implement the MessageRepository interface.
The following methods are required:
-
get()Used to get one message object with a specified
idfrom the database. Returnsnullwhen the object doesn't exist.1suspend fun get(id: MessageId): OUT? -
getList()Returns the list of all messages from a specified
id.1suspend fun getList(
2 id: ChannelId,
3 count: Int,
4 before: Boolean,
5 timestamp: Timetoken,
6): List<OUT>These are the expected arguments:
Name Type Description idChannelIdSpecifies a channel to return messages from. countIntSpecifies the number of messages to return. beforeBooleanRetrieves history messages before or after a specified timestamp.timestampTimetokenGets messages before or after a given time, based on the value in the beforefield. -
getAll()Returns a paginated source of channels.
1fun getAll(
2 id: ChannelId? = null,
3 contentType: String? = null,
4 filter: Query? = null,
5 vararg sorted: Sorted = emptyArray(),
6): PagingSource<Int, OUT>Possible arguments are:
Name Type Description idChannelId?If specified, it returns only messages from a specified ID. contentTypeString?If a message contains any extra content, this field describes its type. Currently, PubNub Chat Components support only text messages. filterQuery?Query filter for the database. sortedArray<Sorted>Array of sorted keys and directions. Example:
1val repository: DefaultMessageRepository = LocalMessageRepository.current
2
3val messages = remember {
4 repository.getAll(
5 id = "my-channel-id",
6 contentType = "default",
7 filter = Query("publisher LIKE ?", "my-userId"),
8 sorted = arrayOf(Sorted("contentType", Sorted.Direction.ASC)),
9 )
10} -
getLast()Returns the last message from a given channel.
1suspend fun getLast(channelId: String): OUT? -
getLastByChannel()Returns a flowable list of most recent messages (in a specified number) from a given channel.
1fun getLastByChannel(id: ChannelId, count: Long): Flow<List<OUT>>Name Type Description idStringChannels to return messages from a specified ID. countLongNumber of messages to return. -
has()Checks if there is a message with a specified ID in the database.
1suspend fun has(id: MessageId): Boolean -
hasMoreBefore()Returns
truewhen any message with older timestamp than specified exists in the database for a given channel.1suspend fun hasMoreBefore(id: ChannelId, timestamp: Timetoken): Boolean -
hasMoreAfter()Returns
truewhen any message with a newer timestamp than specified exists in a database for a given channel.1suspend fun hasMoreAfter(id: ChannelId, timestamp: Timetoken): Boolean -
remove()Removes a message object from the database.
1suspend fun remove(message: IN) -
removeAll()Removes all messages from a given channel.
1suspend fun removeAll(id: ChannelId) -
insertOrUpdate()Sets or updates a message object in the database.
1suspend fun insertOrUpdate(vararg message: IN) -
setSent()Sets the message sent status.
1suspend fun setSent(
2 id: MessageId,
3 timestamp: Timetoken? = null,
4) -
setSendingError()Sets the message error status.
1suspend fun setSendingError(
2 id: MessageId,
3 exception: String? = null,
4 timestamp: Timetoken? = null,
5) -
getLastTimestamp()Returns the last known timestamp of the message in the channel.
1suspend fun getLastTimestamp(id: ChannelId): Timetoken
Network data
The NetworkMessage class is used to communicate with PubNub APIs. The message field is mapped to the NetworkMessagePayload class:
| Name | Type | Description |
|---|---|---|
id | String | Unique identifier for the object. Used as a primary key. |
text | String | Text of the message. |
contentType | String? | If a message contains any extra content, this field describes its type. Currently, PubNub Chat Components support only text messages. |
content | Any? | Extra content for the message like feature-specific data like URLs to external images. |
createdAt | String | ISO8601 date string of when the message was created. |
custom | Any? | Custom key value pairs that can be stored with the message. |
Custom message data
The NetworkMessagePayload contains the custom property. This one might be used to store custom object. In default implementation, the NetworkMessageMapper and NetworkMessageHistoryMapper are used to map it.
Service
PubNub Chat Components for Android use a default service named DefaultMessageService. This service is responsible for synchronizing PubNub APIs network message data and storing it in the local database.
You can obtain the instance or override it using LocalMessageService in CompositionLocalProvider. If you want to use a custom service, you need to create a class which implements the MessageService interface.
Default message service
The DefaultMessageService implementation is defined with the following attributes:
| Name | Type | Description |
|---|---|---|
pubNub | PubNub | PubNub instance. |
userId | userId | ID of the current user. |
messageRepository | MessageRepository<DBMessage, DBMessageWithActions> | The messageRepository implementation responsible for CRUD operations (Create, Read, Update, Delete) on message objects in the database. |
messageActionRepository | MessageActionRepository<DBMessageAction> | The messageActionRepository implementation responsible for CRUD operations (Create, Read, Update, Delete) on message action objects in the database. |
networkMapper | NetworkMessageMapper | Network object to database object mapper. |
networkHistoryMapper | NetworkMessageHistoryMapper | Network history object to database object mapper. |
messageActionHistoryMapper | NetworkMessageActionHistoryMapper | Network message action history object to database object mapper. |
logger | Logger | Instance of the logging class. |
coroutineScope | CoroutineScope | Scope for new coroutines. |
dispatcher | CoroutineDispatcher | Coroutine dispatcher implementation. |
Custom message service
To create a custom member service, implement the MessageService interface and pass it as a parameter to the composition tree. You can do it by wrapping ChatProvider with CompositionLocalProvider:
1CompositionLocalProvider(LocalMessageService provides MyMessageServiceImpl){
2 ChatProvider(…)
3 }
These are the required methods:
-
bind()Sets listeners for message events.
1fun bind() -
unbind()Removes the listeners.
1fun unbind() -
send()Sends a message to a selected channel.
1suspend fun send(
2 channelId: ChannelId,
3 message: NetworkMessagePayload,
4 meta: Any? = null,
5 store: Boolean = true,
6 onSuccess: (String, Timetoken) -> Unit = { _: String, _: Timetoken -> },
7 onError: (Exception) -> Unit = {},
8)These are the expected arguments:
Name Type Description idChannelIdSpecifies a channel to send a message to. messageDataMessage data object to send. metaAny?Additional metadata to send. storeBooleanThe flag denoting to store a message in history. onSuccess(String, Timetoken) -> UnitCallback to invoke when a message is sent successfully. onError(Exception) -> UnitCallback to invoke when there is an error while sending a message. -
fetchAll()Pulls the messages from the PubNub Message Persistence API.
1suspend fun fetchAll(
2 id: ChannelId,
3 start: Long?,
4 end: Long?,
5 count: Int,
6 withActions: Boolean = false,
7 withUUID: Boolean = false,
8): NetworkHistorySyncResult?These are the expected arguments:
Name Type Description idChannelIdSpecifies a channel to return history messages from. startLong?Delimits the start of a time slice (exclusive) to pull messages from. endLong?Delimits the end of a time slice (inclusive) to pull messages from. countIntSpecifies the number of historical messages to return. withActionsBooleanRetrieves history messages with message reactions. withUUIDBooleanIncludes a publisher User ID with every history message.
This method returns the NetworkHistorySyncResult object containing such information about received messages as the smallest and largest timetoken, last page, and message count.
1data class NetworkHistorySyncResult(
2 val minTimetoken: Timetoken?,
3 val maxTimetoken: Timetoken?,
4 val page: PNBoundedPage?,
5 val messageCount: Int,
6)
Message Reactions
A message reaction is an emoji that a user adds to a message to react to it.
Persistent data
The default Persistent Object Model inside the Chat Components defines an Entity named DBMessageAction.
If a custom Persistent Object Model is used, then an Entity must implement the MessageAction interface before it can be used by the Chat Components framework.
DBMessageWithActions
DBMessageWithActions is the relation between a message and all its actions. Both are stored independently but merged together to one data object when returned from the database. They are related through the DBMessage::timetoken and DBMessageAction::messageTimestamp entires.
1data class DBMessageWithActions(
2 @Embedded
3 val message: DBMessage,
4
5 @Relation(
6 parentColumn = "timetoken",
7 entityColumn = "messageTimestamp"
8 )
9 val actions: List<DBMessageAction>,
10) : Message by message
Default message reaction entity
The DBMessageAction entity is defined with the following attributes:
| Name | Type | Description |
|---|---|---|
channel | ChannelId | ID of the channel on which you add a message reaction. |
user | UserId | ID of the user who selects a reaction. |
messageTimestamp | Timetoken | Time when a message to which you react was published. |
published | Timetoken | Time when a reaction was added. |
type | String | The "reaction" type of the action you made. |
value | String | Reaction's value. |
Custom message reaction entity
To create a custom Persistent Object Model, you must implement the MessageAction interface.
The following properties are required:
1interface MessageAction {
2 val id: String
3 val channel: ChannelId
4 val user: UserId
5 val messageTimestamp: Timetoken
6 val published: Timetoken
7 val type: String
8 val value: String
9}
Repository
PubNub Chat Components for Android use a default message reaction repository named DefaultMessageActionRepository.
If you want to use a custom Persistent Object Model, a Repository must implement the MessageActionRepository interface before it can be used by the Chat Components framework. Also, you must implement a custom view model.
Default message reaction repository
The DefaultMessageActionRepository implementation is defined with the following attributes:
| Name | Type | Description |
|---|---|---|
messageActionDao | MessageActionDao<DBMessageAction> | Room DAO for the message entity. |
The MessageActionDao interface uses the DBMessageAction type for CRUD operations (Create, Read, Update, Delete) and to define the type of the returned object.
Custom message reaction repository
To create a custom message repository, implement the MessageActionRepository interface.
The following methods are required:
-
get()Returns a message action for the provided parameters.
1suspend fun get(
2 user: UserId,
3 channel: ChannelId,
4 messageTimetoken: Timetoken,
5 type: String,
6 value: String,
7): DB?These are the expected arguments:
Name Type Description userUserIdSpecifies a user who added the reaction. channelChannelIdSpecifies the channel on which the reaction was added. messageTimetokenTimetokenRetrieves information on the time when the message a given user reacted to was sent. typeStringGets information on the action type ( "reaction").valueStringGets information on the reaction value, like "\uD83D\uDC4D"which stands for "thumbs up". -
has()Checks if a given message reaction exists in the database.
1suspend fun has(id: String): BooleanName Type Description idStringID of a message reaction to check. -
remove()Removes a given message reaction from the database.
1suspend fun remove(vararg action: DB)Name Type Description vararg actionDBDBMessageActionobject to remove. -
insertOrUpdate()Sets or updates a given
DBMessageActionobject in the database.1suspend fun insertOrUpdate(vararg action: DB)Name Type Description vararg actionDBDBMessageActionobject to add or update. -
getLastTimetoken()Returns the last known timestamp of the message reaction in the channel.
1suspend fun getLastTimetoken(channel: ChannelId): TimetokenName Type Description channelChannelIdChannel where a message reaction was added.
Network data
The PNMessageAction class is used to communicate with PubNub APIs to send or receive message actions (inluding reactions).
| Name | Type | Description |
|---|---|---|
type | String | Message action type ("reaction" for message reactions). |
value | String | Message reaction value, like "\uD83D\uDC4D" which stands for "thumbs up". |
messageTimetoken | Timetoken | Time when the message a given user reacted to was sent. |
Service
PubNub Chat Components for Android use a default reaction service named DefaultMessageReactionService. This service is responsible for synchronizing PubNub APIs network message reaction data and storing it in the local database.
You can obtain the instance or override it using LocalMessageReactionService in CompositionLocalProvider. If you want to use a custom service, you need to create a class which implements the MessageReactionService interface.
Default message reaction service
The DefaultMessageReactionService implementation is defined with the following attributes:
| Name | Type | Description |
|---|---|---|
userId | UserId | ID of the current user. |
actionService | ActionService | Generic implementation of message actions. It's not solely restricted to message reactions but could also be used to implement read receipts or channel invitations. It listens for incoming message actions, adding, removing, and fetching actions from PubNub API. |
messageActionRepository | MessageActionRepository<DBMessageAction> | The MessageRepository implementation responsible for CRUD operations (Create, Read, Update, Delete) on message actions objects in the database. |
mapper | Mapper<PNMessageActionResult, DBMessageAction> | Network history object to database object mapper. |
logger | Logger | Instance of the logging class. |
coroutineScope | CoroutineScope | Scope for new coroutines. |
dispatcher | CoroutineDispatcher | Coroutine dispatcher implementation. |
Custom message reaction service
To create a custom message reaction service, implement the MessageReactionService interface and pass it as a parameter to the composition tree. You can do it by wrapping ChatProvider with CompositionLocalProvider:
1CompositionLocalProvider(LocalMessageReactionService provides MyMessageReactionService){
2 ChatProvider(…)
3}
These are the required methods:
-
bind()Sets listeners for the message reactions.
1fun bind(
2 types: Array<String> = arrayOf("reaction")
3 )Name Type Description typesArray<String> = arrayOf("reaction")Refers to the accepted message action type ( "reaction") that will be stored in the database. -
unbind()Stops listening for message reactions.
1fun bind() -
synchronize()Synchronizes message reactions for the provided channel.
1fun synchronize(
2 channel: ChannelId,
3 lastTimetoken: Timetoken? = null
4 )Name Type Description channelChannelIdID of the channel to synchronize. lastTimetokenTimetoken? = nullLast synchronization timestamp. -
add()Adds a specific message reaction to the PubNub API and the local repository.
1suspend fun add(
2 channel: ChannelId,
3 messageTimetoken: Timetoken,
4 type: String,
5 value: String
6 )Name Type Description channelChannelIdID of the channel where the message reaction was added. messageTimetokenTimetokenTime when the message a given user reacted to was sent. typeStringMessage action type ( "reaction").valueStringMessage reaction value. -
remove()Removes a specific message reaction from the PubNub API and the local repository.
1suspend fun remove(
2 channel: ChannelId,
3 messageTimetoken: Timetoken,
4 published: Timetoken,
5 type: String,
6 value: String
7 )Name Type Description channelChannelIdID of the channel where the message reaction was added. messageTimetokenTimetokenTime when the message a given user reacted to was sent. publishedTimetokenTime when the message reaction was added. typeStringMessage action type ( "reaction").valueStringMessage reaction value.