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
ViewModel
method 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
DataProvider
or 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:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "User",
"type": "object",
"description": "User of a chat application",
"properties": {
"id": {
"description": "Unique identifier for a user",
"type": "string"
},
"name": {
"description": "Name of the user that you can display in the UI",
"type": "string"
},
"email": {
show all 58 linesExample:
{
"id": "some-user-id",
"name": "Jane Doe",
"email": "jane.doe@example.com",
"externalId": "some-external-user-id",
"profileUrl": "https://randomuser.me/api/portraits/men/1.jpg",
"type": "default",
"status": "default",
"custom": {
"description": "Office Assistant",
},
"eTag": "AYGyoY3gre71eA",
"updated": "2020-09-23T09:23:34.598494Z"
}
Channels
Follow this schema for the channel data in your apps:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Channel",
"description": "Channel in the chat application",
"type": "object",
"properties": {
"id": {
"description": "Unique identifier for a channel",
"type": "string"
},
"name": {
"description": "Name of the channel that you can display in the UI",
"type": "string"
},
"description": {
show all 50 linesExample:
{
"id": "some-channel-id",
"name": "Off-topic",
"description": "Off-topic channel for random chatter and fun",
"type": "default",
"status": "default",
"custom": {
"profileUrl": "https://www.gravatar.com/avatar/149e60f311749f2a7c6515f7b34?s=256&d=identicon"
},
"eTag": "AbOx6N+6vu3zoAE",
"updated": "2020-09-23T09:23:37.175764Z"
}
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.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Message Content",
"description": "Message content in the chat application",
"type": "object",
"properties": {
"id": {
"description": "Unique identifier for a message. Use the UUID v4 algorithm.",
"type": "string"
},
"text": {
"description": "Text of the message that you can display in the UI",
"type": "string"
},
"contentType": {
show all 34 linesExample:
{
"id": "6da72b98-e211-4724-aad4-e0fb9f08999f",
"text": "Let's sync on the topic in this thread.",
"contentType": "none",
"content": {},
"custom": {},
"createdAt": "2022-05-10T14:48:00.000Z"
}
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.
typealias 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:
interface Channel {
val id: ChannelId
val name: String?
val description: String?
val type: String
val status: String?
val custom: Any?
val profileUrl: String?
val eTag: String?
val updated: String?
}
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
Channel
object with specifiedid
from the database. It returnsnull
when the object doesn't exist.suspend fun get(id: ChannelId): OUT?
-
getAll()
Returns the paginated source of channels.
fun getAll(
id: UserId? = null,
filter: Query? = null,
vararg sorted: Sorted = emptyArray(),
): PagingSource<Int, OUT>Name Type Description id
UserId?
If specified, this method returns only channels the user is a member of. filter
Query?
Query filter for the database. sorted
Sorted
Array of sorted keys and directions. Example:
val repository: DefaultChannelRepository = LocalChannelRepository.current
val channels = remember {
repository.getAll(
id = "my-user-id",
filter = Query("type LIKE ?", "group"),
sorted = arrayOf(Sorted("type", Sorted.Direction.ASC)),
)
} -
getList()
Returns the list of all channels.
suspend fun getList(): List<OUT>
-
insertOrUpdate()
Sets or updates a channel object in the database.
suspend fun insertOrUpdate(vararg channel: IN)
-
remove()
Removes the channel object with the specified ID.
suspend fun remove(id: ChannelId)
-
size()
Returns the number of all channels.
suspend 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
.
CompositionLocalProvider(LocalChannelService provides MyChannelServiceImpl){
ChatProvider(…)
}
These are the required methods:
-
bind()
Subscribes to the channels and sets listeners for channel events.
fun bind(vararg channels: String)
-
unbind()
Removes the listeners and unsubscribes from channels.
fun 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:
interface Member {
val id: UserId
val name: String
val email: String?
val externalId: String?
val profileUrl: String?
val type: String
val status: String?
val custom: Any?
val eTag: String?
val updated: String?
}
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
id
from the database. Returnsnull
when the object doesn't exist.suspend fun get(id: UserId): OUT?
-
getAll()
Returns paginated source of members. Possible arguments are:
fun getAll(
id: ChannelId? = null,
filter: Query? = null,
vararg sorted: Sorted = emptyArray(),
): PagingSource<Int, OUT>Name Type Description id
ChannelId?
If specified, returns all members of the channel with the specified ID. filter
Query?
Query filter for the database. sorted
Sorted
Array of sorted keys and directions. Example:
val repository: DefaultMemberRepository = LocalMemberRepository.current
val members = remember {
repository.getAll(
id = "channel-id",
filter = Query("name LIKE ?", "Android"),
sorted = arrayOf(Sorted("name", Sorted.Direction.ASC)),
)
} -
getList()
If
id
is specified, it returns the list of members of the specified channel. Otherwise, it returns the list of all members.suspend fun getList(id: ChannelId? = null): List<OUT>
-
insertOrUpdate()
Sets or updates a member object in the database.
suspend fun insertOrUpdate(vararg member: IN)
-
remove()
Removes the member object with the specified ID.
suspend fun remove(id: UserId)
-
size()
Returns the number of all members.
suspend 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:
interface Message {
val id: MessageId
val text: String
val contentType: String?
val content: Any?
val createdAt: String
val custom: Any?
}
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
id
from the database. Returnsnull
when the object doesn't exist.suspend fun get(id: MessageId): OUT?
-
getList()
Returns the list of all messages from a specified
id
.suspend fun getList(
id: ChannelId,
count: Int,
before: Boolean,
timestamp: Timetoken,
): List<OUT>These are the expected arguments:
Name Type Description id
ChannelId
Specifies a channel to return messages from. count
Int
Specifies the number of messages to return. before
Boolean
Retrieves history messages before or after a specified timestamp
.timestamp
Timetoken
Gets messages before or after a given time, based on the value in the before
field. -
getAll()
Returns a paginated source of channels.
fun getAll(
id: ChannelId? = null,
contentType: String? = null,
filter: Query? = null,
vararg sorted: Sorted = emptyArray(),
): PagingSource<Int, OUT>Possible arguments are:
Name Type Description id
ChannelId?
If specified, it returns only messages from a specified ID. contentType
String?
If a message contains any extra content, this field describes its type. Currently, PubNub Chat Components support only text messages. filter
Query?
Query filter for the database. sorted
Array<Sorted>
Array of sorted keys and directions. Example:
val repository: DefaultMessageRepository = LocalMessageRepository.current
val messages = remember {
repository.getAll(
id = "my-channel-id",
contentType = "default",
filter = Query("publisher LIKE ?", "my-userId"),
sorted = arrayOf(Sorted("contentType", Sorted.Direction.ASC)),
)
} -
getLast()
Returns the last message from a given channel.
suspend fun getLast(channelId: String): OUT?
-
getLastByChannel()
Returns a flowable list of most recent messages (in a specified number) from a given channel.
fun getLastByChannel(id: ChannelId, count: Long): Flow<List<OUT>>
Name Type Description id
String
Channels to return messages from a specified ID. count
Long
Number of messages to return. -
has()
Checks if there is a message with a specified ID in the database.
suspend fun has(id: MessageId): Boolean
-
hasMoreBefore()
Returns
true
when any message with older timestamp than specified exists in the database for a given channel.suspend fun hasMoreBefore(id: ChannelId, timestamp: Timetoken): Boolean
-
hasMoreAfter()
Returns
true
when any message with a newer timestamp than specified exists in a database for a given channel.suspend fun hasMoreAfter(id: ChannelId, timestamp: Timetoken): Boolean
-
remove()
Removes a message object from the database.
suspend fun remove(message: IN)
-
removeAll()
Removes all messages from a given channel.
suspend fun removeAll(id: ChannelId)
-
insertOrUpdate()
Sets or updates a message object in the database.
suspend fun insertOrUpdate(vararg message: IN)
-
setSent()
Sets the message sent status.
suspend fun setSent(
id: MessageId,
timestamp: Timetoken? = null,
) -
setSendingError()
Sets the message error status.
suspend fun setSendingError(
id: MessageId,
exception: String? = null,
timestamp: Timetoken? = null,
) -
getLastTimestamp()
Returns the last known timestamp of the message in the channel.
suspend 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
:
CompositionLocalProvider(LocalMessageService provides MyMessageServiceImpl){
ChatProvider(…)
}
These are the required methods:
-
bind()
Sets listeners for message events.
fun bind()
-
unbind()
Removes the listeners.
fun unbind()
-
send()
Sends a message to a selected channel.
suspend fun send(
channelId: ChannelId,
message: NetworkMessagePayload,
meta: Any? = null,
store: Boolean = true,
onSuccess: (String, Timetoken) -> Unit = { _: String, _: Timetoken -> },
onError: (Exception) -> Unit = {},
)These are the expected arguments:
Name Type Description id
ChannelId
Specifies a channel to send a message to. message
Data
Message data object to send. meta
Any?
Additional metadata to send. store
Boolean
The flag denoting to store a message in history. onSuccess
(String, Timetoken) -> Unit
Callback to invoke when a message is sent successfully. onError
(Exception) -> Unit
Callback to invoke when there is an error while sending a message. -
fetchAll()
Pulls the messages from the PubNub Message Persistence API.
suspend fun fetchAll(
id: ChannelId,
start: Long?,
end: Long?,
count: Int,
withActions: Boolean = false,
withUUID: Boolean = false,
): NetworkHistorySyncResult?These are the expected arguments:
Name Type Description id
ChannelId
Specifies a channel to return history messages from. start
Long?
Delimits the start of a time slice (exclusive) to pull messages from. end
Long?
Delimits the end of a time slice (inclusive) to pull messages from. count
Int
Specifies the number of historical messages to return. withActions
Boolean
Retrieves history messages with message reactions. withUUID
Boolean
Includes 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.
data class NetworkHistorySyncResult(
val minTimetoken: Timetoken?,
val maxTimetoken: Timetoken?,
val page: PNBoundedPage?,
val messageCount: Int,
)
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.
data class DBMessageWithActions(
@Embedded
val message: DBMessage,
@Relation(
parentColumn = "timetoken",
entityColumn = "messageTimestamp"
)
val actions: List<DBMessageAction>,
) : 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:
interface MessageAction {
val id: String
val channel: ChannelId
val user: UserId
val messageTimestamp: Timetoken
val published: Timetoken
val type: String
val value: String
}
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.
suspend fun get(
user: UserId,
channel: ChannelId,
messageTimetoken: Timetoken,
type: String,
value: String,
): DB?These are the expected arguments:
Name Type Description user
UserId
Specifies a user who added the reaction. channel
ChannelId
Specifies the channel on which the reaction was added. messageTimetoken
Timetoken
Retrieves information on the time when the message a given user reacted to was sent. type
String
Gets information on the action type ( "reaction"
).value
String
Gets information on the reaction value, like "\uD83D\uDC4D"
which stands for "thumbs up". -
has()
Checks if a given message reaction exists in the database.
suspend fun has(id: String): Boolean
Name Type Description id
String
ID of a message reaction to check. -
remove()
Removes a given message reaction from the database.
suspend fun remove(vararg action: DB)
Name Type Description vararg action
DB
DBMessageAction
object to remove. -
insertOrUpdate()
Sets or updates a given
DBMessageAction
object in the database.suspend fun insertOrUpdate(vararg action: DB)
Name Type Description vararg action
DB
DBMessageAction
object to add or update. -
getLastTimetoken()
Returns the last known timestamp of the message reaction in the channel.
suspend fun getLastTimetoken(channel: ChannelId): Timetoken
Name Type Description channel
ChannelId
Channel 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
:
CompositionLocalProvider(LocalMessageReactionService provides MyMessageReactionService){
ChatProvider(…)
}
These are the required methods:
-
bind()
Sets listeners for the message reactions.
fun bind(
types: Array<String> = arrayOf("reaction")
)Name Type Description types
Array<String> = arrayOf("reaction")
Refers to the accepted message action type ( "reaction"
) that will be stored in the database. -
unbind()
Stops listening for message reactions.
fun bind()
-
synchronize()
Synchronizes message reactions for the provided channel.
fun synchronize(
channel: ChannelId,
lastTimetoken: Timetoken? = null
)Name Type Description channel
ChannelId
ID of the channel to synchronize. lastTimetoken
Timetoken? = null
Last synchronization timestamp. -
add()
Adds a specific message reaction to the PubNub API and the local repository.
suspend fun add(
channel: ChannelId,
messageTimetoken: Timetoken,
type: String,
value: String
)Name Type Description channel
ChannelId
ID of the channel where the message reaction was added. messageTimetoken
Timetoken
Time when the message a given user reacted to was sent. type
String
Message action type ( "reaction"
).value
String
Message reaction value. -
remove()
Removes a specific message reaction from the PubNub API and the local repository.
suspend fun remove(
channel: ChannelId,
messageTimetoken: Timetoken,
published: Timetoken,
type: String,
value: String
)Name Type Description channel
ChannelId
ID of the channel where the message reaction was added. messageTimetoken
Timetoken
Time when the message a given user reacted to was sent. published
Timetoken
Time when the message reaction was added. type
String
Message action type ( "reaction"
).value
String
Message reaction value.