Skip to content

Commit

Permalink
[ECO-5082] feat: add presence popup for example app
Browse files Browse the repository at this point in the history
  • Loading branch information
ttypic committed Nov 7, 2024
1 parent f3eeb2a commit 9412107
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 9 deletions.
49 changes: 40 additions & 9 deletions example/src/main/java/com/ably/chat/example/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,16 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
Expand All @@ -38,6 +44,7 @@ import com.ably.chat.Message
import com.ably.chat.RealtimeClient
import com.ably.chat.SendMessageParams
import com.ably.chat.SendReactionParams
import com.ably.chat.example.ui.PresencePopup
import com.ably.chat.example.ui.theme.AblyChatExampleTheme
import io.ably.lib.types.ClientOptions
import java.util.UUID
Expand All @@ -62,17 +69,40 @@ class MainActivity : ComponentActivity() {
enableEdgeToEdge()
setContent {
AblyChatExampleTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Chat(
chatClient,
modifier = Modifier.padding(innerPadding),
)
}
App(chatClient)
}
}
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun App(chatClient: ChatClient) {
var showPopup by remember { mutableStateOf(false) }

Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
TopAppBar(
title = { Text("Chat") },
actions = {
IconButton(onClick = { showPopup = true }) {
Icon(Icons.Default.Person, contentDescription = "Show members")
}
},
)
},
) { innerPadding ->
Chat(
chatClient,
modifier = Modifier.padding(innerPadding),
)
if (showPopup) {
PresencePopup(chatClient, onDismiss = { showPopup = false })
}
}
}

@SuppressWarnings("LongMethod")
@Composable
fun Chat(chatClient: ChatClient, modifier: Modifier = Modifier) {
Expand All @@ -83,8 +113,7 @@ fun Chat(chatClient: ChatClient, modifier: Modifier = Modifier) {
val coroutineScope = rememberCoroutineScope()
var receivedReactions by remember { mutableStateOf<List<String>>(listOf()) }

val roomId = "my-room"
val room = chatClient.rooms.get(roomId)
val room = chatClient.rooms.get(Settings.ROOM_ID)

DisposableEffect(Unit) {
coroutineScope.launch {
Expand Down Expand Up @@ -130,7 +159,9 @@ fun Chat(chatClient: ChatClient, modifier: Modifier = Modifier) {
verticalArrangement = Arrangement.SpaceBetween,
) {
LazyColumn(
modifier = Modifier.weight(1f).padding(16.dp),
modifier = Modifier
.weight(1f)
.padding(16.dp),
userScrollEnabled = true,
state = listState,
) {
Expand Down
5 changes: 5 additions & 0 deletions example/src/main/java/com/ably/chat/example/Settings.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.ably.chat.example

object Settings {
const val ROOM_ID = "my-room"
}
109 changes: 109 additions & 0 deletions example/src/main/java/com/ably/chat/example/ui/PresencePopup.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.ably.chat.example.ui

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.text.BasicText
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Popup
import com.ably.chat.ChatClient
import com.ably.chat.PresenceMember
import com.ably.chat.Subscription
import com.ably.chat.example.Settings
import com.google.gson.JsonObject
import kotlinx.coroutines.launch

@SuppressWarnings("LongMethod")
@Composable
fun PresencePopup(chatClient: ChatClient, onDismiss: () -> Unit) {
var members by remember { mutableStateOf(listOf<PresenceMember>()) }
val coroutineScope = rememberCoroutineScope()
val presence = chatClient.rooms.get(Settings.ROOM_ID).presence

DisposableEffect(Unit) {
var subscription: Subscription? = null

coroutineScope.launch {
members = presence.get()
subscription = presence.subscribe {
coroutineScope.launch {
members = presence.get()
}
}
}

onDispose {
subscription?.unsubscribe()
}
}

Popup(
onDismissRequest = onDismiss,
) {
Surface(
modifier = Modifier.padding(16.dp),
shape = MaterialTheme.shapes.medium,
shadowElevation = 8.dp,
) {
Column(
modifier = Modifier
.padding(16.dp)
.wrapContentWidth(),
) {
Text("Chat Members", style = MaterialTheme.typography.headlineMedium)
Spacer(modifier = Modifier.height(8.dp))
members.forEach { member ->
BasicText("${member.clientId} - (${(member.data as? JsonObject)?.get("status")?.asString})")
Spacer(modifier = Modifier.height(4.dp))
}
Spacer(modifier = Modifier.height(8.dp))
Button(onClick = {
coroutineScope.launch {
presence.enter(
JsonObject().apply {
addProperty("status", "online")
},
)
}
}) {
Text("Join")
}
Button(onClick = {
coroutineScope.launch {
presence.enter(
JsonObject().apply {
addProperty("status", "away")
},
)
}
}) {
Text("Appear away")
}
Button(onClick = {
coroutineScope.launch {
presence.leave()
}
}) {
Text("Leave")
}
Button(onClick = onDismiss) {
Text("Close")
}
}
}
}
}

0 comments on commit 9412107

Please sign in to comment.