Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/data/languages/languageData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ export default {
javascript: '1.1',
react: '1.1',
swift: '1.0',
kotlin: '1.0',
kotlin: '1.1',
jetpack: '1.1',
},
spaces: {
javascript: '0.4',
Expand Down
5 changes: 5 additions & 0 deletions src/data/languages/languageInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ export default {
label: 'Kotlin',
syntaxHighlighterKey: 'kotlin',
},
jetpack: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added these as a fixup so that it shows up in docs - could you source an icon for Jetpack so it shows in the language selector?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added alias to kotlin, so it will use kotlin icon for now

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created PR to add icon -> ably/ably-ui#1023

label: 'Jetpack Compose',
syntaxHighlighterKey: 'kotlin',
alias: 'kotlin',
},
realtime: {
label: 'Realtime',
syntaxHighlighterKey: 'javascript',
Expand Down
1 change: 1 addition & 0 deletions src/data/languages/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const languageKeys = [
'css',
'laravel',
'typescript',
'jetpack',
] as const;

export type LanguageKey = (typeof languageKeys)[number];
Expand Down
57 changes: 57 additions & 0 deletions src/pages/docs/chat/connect.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ Use the <If lang="javascript">[`status`](https://sdk.ably.com/builds/ably/ably-c
Use the [`currentStatus`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-react.UseChatConnectionResponse.html#currentStatus) property returned in the response of the [`useChatConnection`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/functions/chat-react.useChatConnection.html) hook to check which status a connection is currently in:
</If>

<If lang="jetpack">
Use the [`collectAsStatus()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/jetpack/chat-extensions-compose/com.ably.chat.extensions.compose/collect-as-status.html) composable function to observe the connection status as a State:
</If>

<Code>
```javascript
const connectionStatus = chatClient.connection.status;
Expand Down Expand Up @@ -56,6 +60,17 @@ let status = chatClient.connection.status
```kotlin
val connectionStatus = chatClient.connection.status
```

```jetpack
import com.ably.chat.extensions.compose.collectAsStatus

@Composable
fun MyComponent(chatClient: ChatClient) {
val connectionStatus by chatClient.connection.collectAsStatus()

Text("Connection status: $connectionStatus")
}
```
Comment on lines +64 to +73
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing import statements. The code uses ChatClient type but doesn't import it. Add import for ChatClient and other required types.

Copilot uses AI. Check for mistakes.
</Code>

<If lang="react">
Expand Down Expand Up @@ -84,6 +99,10 @@ Listeners can also be registered to monitor the changes in connection status. An
Use the <If lang="javascript">[`connection.onStatusChange()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Connection.html#onStatusChange)</If><If lang="swift">[`connection.onStatusChange()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/connection/onstatuschange%28%29-76t7)</If><If lang="kotlin">[`connection.status.onStatusChange()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-connection/on-status-change.html)</If> method to register a listener for status change updates:
</If>

<If lang="jetpack">
In Jetpack Compose, you can use [`collectAsStatus()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/jetpack/chat-extensions-compose/com.ably.chat.extensions.compose/collect-as-status.html) to observe status changes reactively:
</If>

<Code>
```javascript
const { off } = chatClient.connection.onStatusChange((change) => console.log(change));
Expand Down Expand Up @@ -114,6 +133,24 @@ val (off) = chatClient.connection.onStatusChange { statusChange: ConnectionStatu
println(statusChange.toString())
}
```

```jetpack
import androidx.compose.material.*
import androidx.compose.runtime.*
import com.ably.chat.ChatClient
import com.ably.chat.extensions.compose.collectAsStatus

@Composable
fun MyComponent(chatClient: ChatClient) {
val connectionStatus by chatClient.connection.collectAsStatus()

LaunchedEffect(connectionStatus) {
println("Connection status changed to: $connectionStatus")
}

Text("Connection status: $connectionStatus")
}
```
</Code>

<If lang="javascript,kotlin">
Expand Down Expand Up @@ -148,6 +185,10 @@ The Chat SDK provides an `onDiscontinuity()` handler exposed via the Room object
Any hooks that take an optional listener to monitor their events, such as typing indicator events in the `useTyping` hook, can also register a listener to be notified of, and handle, periods of discontinuity.
</If>

<If lang="jetpack">
Use the [`discontinuityAsFlow()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/discontinuity-as-flow.html) extension function to observe discontinuity events as a Flow in Jetpack Compose:
</If>

For example, for messages:

<Code>
Expand Down Expand Up @@ -184,6 +225,22 @@ val (off) = room.onDiscontinuity { reason: ErrorInfo ->
// Recover from the discontinuity
}
```

```jetpack
import androidx.compose.runtime.*
import com.ably.chat.Room
import com.ably.chat.discontinuityAsFlow

@Composable
fun MyComponent(room: Room) {
LaunchedEffect(room) {
room.discontinuityAsFlow().collect { error ->
// Recover from the discontinuity
println("Discontinuity detected: $error")
}
}
}
```
</Code>

<If lang="javascript,kotlin">
Expand Down
45 changes: 21 additions & 24 deletions src/pages/docs/chat/getting-started/android.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ fun ChatBox(room: Room?) {
var sending by remember { mutableStateOf(false) }
val messages = remember { mutableStateListOf<Message>() }

DisposableEffect(room) {
val subscription = room?.messages?.subscribe { event ->
LaunchedEffect(room) {
room?.messages?.asFlow()?.collect { event ->
when (event.type) {
MessageEventType.Created -> {
// Check if the incoming message is correctly ordered
Expand All @@ -266,10 +266,6 @@ fun ChatBox(room: Room?) {
else -> Unit
}
}

onDispose {
subscription?.unsubscribe()
}
}

Column(
Expand Down Expand Up @@ -445,8 +441,8 @@ var edited: Message? by remember { mutableStateOf(null) }

<Code>
```kotlin
DisposableEffect(room) {
val subscription = room?.messages?.subscribe { event ->
LaunchedEffect(room) {
room?.messages?.asFlow()?.collect { event ->
when (event.type) {
MessageEventType.Created -> messages.add(0, event.message)
MessageEventType.Updated -> messages.replaceFirstWith(event.message) {
Expand All @@ -455,10 +451,6 @@ DisposableEffect(room) {
else -> Unit
}
}

onDispose {
subscription?.unsubscribe()
}
}
```
</Code>
Expand Down Expand Up @@ -543,17 +535,18 @@ When you click on the edit button in the UI, you can modify the text and it will

## Step 6: Message history and continuity <a id="step-6"/>

Ably Chat enables you to retrieve previously sent messages in a room. This is useful for providing conversational context when a user first joins a room, or when they subsequently rejoin it later on. The message subscription object exposes the [`getPreviousMessages()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages-subscription/get-previous-messages.html) method to enable this functionality. This method returns a paginated response, which can be queried further to retrieve the next set of messages.
Ably Chat enables you to retrieve previously sent messages in a room. This is useful for providing conversational context when a user first joins a room, or when they subsequently rejoin it later on. The message subscription object exposes the [`historyBeforeSubscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages-subscription/history-before-subscribe.html) method to enable this functionality. This method returns a paginated response, which can be queried further to retrieve the next set of messages.

Extend the `ChatBox` component to include a method to retrieve the last 10 messages when the component mounts. In your `MainActivity.kt` file, add the `DisposableEffect` in your `ChatBox` component:

<Code>
```kotlin
fun ChatBox(room: Room?) {
/* variables declaration */
var subscription by remember { mutableStateOf<MessagesSubscription?>(null) }

DisposableEffect(room) {
val subscription = room?.messages?.subscribe { event ->
subscription = room?.messages?.subscribe { event ->
when (event.type) {
MessageEventType.Created -> messages.add(0, event.message)
MessageEventType.Updated -> messages.replaceFirstWith(event.message) {
Expand All @@ -563,16 +556,19 @@ fun ChatBox(room: Room?) {
}
}

scope.launch {
val previousMessages = subscription?.historyBeforeSubscribe(10)?.items ?: emptyList()
messages.addAll(previousMessages)
}

onDispose {
subscription?.unsubscribe()
}
}
/* rest of your code */
}

LaunchedEffect(subscription) {
subscription?.let { sub ->
val previousMessages = sub.historyBeforeSubscribe(10)?.items ?: emptyList()
messages.addAll(previousMessages)
}
}

/* rest of your code */
}
```
</Code>
Expand Down Expand Up @@ -709,7 +705,7 @@ fun ChatBox(room: Room?) {
Do the following to test this out:

1. Use the ably CLI to simulate sending some messages to the room from another client.
2. Refresh the page, this will cause the `ChatBox` component to mount again and call the `getPreviousMessages()` method.
2. Refresh the page, this will cause the `ChatBox` component to mount again and call the `historyBeforeSubscribe()` method.
3. You'll see the last 10 messages appear in the chat box.

## Step 7: Display who is present in the room <a id="step-7"/>
Expand All @@ -722,14 +718,15 @@ In your `MainActivity.kt` file, create a new component called `PresenceStatusUi`
```kotlin
@Composable
fun PresenceStatusUi(room: Room?) {
val members = room?.collectAsPresenceMembers()
val membersState = room?.collectAsPresenceMembers()
val members by membersState ?: remember { mutableStateOf(emptyList()) }

LaunchedEffect(room) {
room?.presence?.enter()
}

Text(
text = "Online: ${members?.size ?: 0}",
text = "Online: ${members.size}",
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(start = 8.dp)
)
Expand Down
80 changes: 79 additions & 1 deletion src/pages/docs/chat/rooms/history.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ The history feature enables users to retrieve messages that have been previously
Use the <If lang="javascript">[`messages.history()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.Messages.html#history)</If><If lang="swift">[`messages.history()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messages/history(withparams:))</If><If lang="kotlin">[`messages.history()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages/history.html)</If> method to retrieve messages that have been previously sent to a room. This returns a paginated response, which can be queried further to retrieve the next set of messages.
</If>

<If lang="jetpack">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above if won't work for jetpack and duplicates this one, so we should pick one

Copy link
Contributor

@sacOO7 sacOO7 Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, we have only kept the lower one

Use the [`collectAsPagingMessagesState()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/jetpack/chat-extensions-compose/com.ably.chat.extensions.compose/collect-as-paging-messages-state.html) method to retrieve messages that have been previously sent to a room. This returns a paginated response, which can be queried further to retrieve the next set of messages.
</If>

<If lang="react">
Use the [`history()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-react.UseMessagesResponse.html#history) method available from the response of the `useMessages` hook to retrieve messages that have been previously sent to a room. This returns a paginated response, which can be queried further to retrieve the next set of messages.
</If>
Expand Down Expand Up @@ -71,6 +75,29 @@ while (historicalMessages.hasNext()) {

println("End of messages")
```

```jetpack
import androidx.compose.foundation.lazy.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import com.ably.chat.OrderBy
import com.ably.chat.Room
import com.ably.chat.extensions.compose.collectAsPagingMessagesState

@Composable
fun HistoryComponent(room: Room) {
val pagingMessagesState by room.messages.collectAsPagingMessagesState(
orderBy = OrderBy.NewestFirst
)

LazyColumn {
items(pagingMessagesState.messages.size) { index ->
val message = pagingMessagesState.messages[index]
Text("Message: ${message.text}")
}
}
}
```
</Code>

The following optional parameters can be passed when retrieving previously sent messages:
Expand All @@ -87,7 +114,11 @@ The following optional parameters can be passed when retrieving previously sent
Users can also retrieve historical messages that were sent to a room before the point that they registered a listener by [subscribing](/docs/chat/rooms/messages#subscribe). The order of messages returned is from most recent, to oldest. This is useful for providing conversational context when a user first joins a room, or when they subsequently rejoin it later on. It also ensures that the message history they see is continuous, without any overlap of messages being returned between their subscription and their history call.

<If lang="javascript,swift,kotlin">
Use the <If lang="javascript">[`historyBeforeSubscribe()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.MessageSubscriptionResponse.html#historyBeforeSubscribe)</If><If lang="swift">[`historyBeforeSubscribe(withParams:)`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messagesubscriptionresponse/historybeforesubscribe%28withparams%3A%29))</If><If lang="kotlin">[`getPreviousMessages()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages-subscription/get-previous-messages.html)</If> function returned as part of a [message subscription](/docs/chat/rooms/messages#subscribe) response to only retrieve messages that were received before the listener was subscribed to the room. This returns a paginated response, which can be queried further to retrieve the next set of messages.
Use the <If lang="javascript">[`historyBeforeSubscribe()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.MessageSubscriptionResponse.html#historyBeforeSubscribe)</If><If lang="swift">[`historyBeforeSubscribe(withParams:)`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/messagesubscriptionresponse/historybeforesubscribe%28withparams%3A%29))</If><If lang="kotlin">[`historyBeforeSubscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages-subscription/history-before-subscribe.html)</If> function returned as part of a [message subscription](/docs/chat/rooms/messages#subscribe) response to only retrieve messages that were received before the listener was subscribed to the room. This returns a paginated response, which can be queried further to retrieve the next set of messages.
</If>

<If lang="jetpack">
Use the [`historyBeforeSubscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-messages-subscription/history-before-subscribe.html) function returned as part of a [message subscription](/docs/chat/rooms/messages#subscribe) response to only retrieve messages that were received before the listener was subscribed to the room. This returns a paginated response, which can be queried further to retrieve the next set of messages.
</If>

<If lang="react">
Expand Down Expand Up @@ -167,6 +198,53 @@ while (historicalMessages.hasNext()) {

println("End of messages")
```

```jetpack
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import com.ably.chat.MessagesSubscription
import com.ably.chat.Room

@Composable
fun HistoryBeforeSubscribeComponent(room: Room) {
var messages by remember { mutableStateOf<List<String>>(emptyList()) }
var subscription by remember { mutableStateOf<MessagesSubscription?>(null) }

DisposableEffect(room) {
subscription = room.messages.subscribe {
println("New message received")
}

onDispose {
subscription?.unsubscribe()
}
}

LaunchedEffect(subscription) {
subscription?.let { sub ->
var historicalMessages = sub.historyBeforeSubscribe(limit = 50)
println(historicalMessages.items.toString())
messages = historicalMessages.items.map { it.text }

while (historicalMessages.hasNext()) {
historicalMessages = historicalMessages.next()
println(historicalMessages.items.toString())
messages = messages + historicalMessages.items.map { it.text }
}

println("End of messages")
}
}

// Display messages in UI
Column {
messages.forEach { message ->
Text(message)
}
}
}
```
</Code>

The following parameters can be passed when retrieving previously sent messages:
Expand Down
Loading