Skip to content

Commit

Permalink
[CHA-848] feat: edit and delete example
Browse files Browse the repository at this point in the history
Added example of edits and deletes to the example app
  • Loading branch information
ttypic committed Feb 26, 2025
1 parent bdf4f7c commit 8c27173
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 18 deletions.
145 changes: 127 additions & 18 deletions example/src/main/java/com/ably/chat/example/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ 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.MoreVert
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
Expand All @@ -43,6 +47,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.ably.chat.ChatClient
import com.ably.chat.Message
import com.ably.chat.MessageEventType
import com.ably.chat.MessageMetadata
import com.ably.chat.Room
import com.ably.chat.RoomOptions
Expand Down Expand Up @@ -146,7 +151,7 @@ fun App(chatClient: ChatClient) {
}
}

@SuppressWarnings("LongMethod")
@SuppressWarnings("LongMethod", "CognitiveComplexMethod")
@Composable
fun Chat(room: Room, modifier: Modifier = Modifier) {
var messageText by remember { mutableStateOf(TextFieldValue("")) }
Expand All @@ -155,12 +160,48 @@ fun Chat(room: Room, modifier: Modifier = Modifier) {
val listState = rememberLazyListState()
val coroutineScope = rememberCoroutineScope()
var receivedReactions by remember { mutableStateOf<List<String>>(listOf()) }
var edited: Message? by remember { mutableStateOf(null) }
val updating = edited != null

val handleSend = {
coroutineScope.launch {
room.messages.send(
text = messageText.text,
)
messageText = TextFieldValue("")
sending = false
}
}

val handleEdit = handleEdit@{
val editedMessage = edited ?: return@handleEdit
coroutineScope.launch {
room.messages.update(
editedMessage.copy(text = messageText.text),
)
messageText = TextFieldValue("")
edited = null
sending = false
}
}

DisposableEffect(Unit) {
val subscription = room.messages.subscribe {
messages += it.message
coroutineScope.launch {
listState.animateScrollToItem(messages.size - 1)
val subscription = room.messages.subscribe { event ->
when (event.type) {
MessageEventType.Created -> {
messages += event.message
coroutineScope.launch {
listState.animateScrollToItem(messages.size - 1)
}
}

MessageEventType.Updated -> messages = messages.map {
if (it.serial != event.message.serial) it else event.message
}

MessageEventType.Deleted -> messages = messages.filter {
it.serial != event.message.serial
}
}
}

Expand Down Expand Up @@ -196,11 +237,23 @@ fun Chat(room: Room, modifier: Modifier = Modifier) {
state = listState,
) {
items(messages.size) { index ->
MessageBubble(messages[index])
MessageBubble(
message = messages[index],
onEdit = {
edited = messages[index]
messageText = TextFieldValue(messages[index].text)
},
onDelete = {
coroutineScope.launch {
room.messages.delete(messages[index])
}
},
)
}
}

ChatInputField(
updating = updating,
sending = sending,
messageInput = messageText,
onMessageChange = {
Expand All @@ -211,12 +264,9 @@ fun Chat(room: Room, modifier: Modifier = Modifier) {
},
onSendClick = {
sending = true
coroutineScope.launch {
room.messages.send(
text = messageText.text,
)
messageText = TextFieldValue("")
sending = false
when {
updating -> handleEdit()
else -> handleSend()
}
},
onReactionClick = {
Expand All @@ -231,8 +281,12 @@ fun Chat(room: Room, modifier: Modifier = Modifier) {
}
}

@Suppress("LongMethod")
@Composable
fun MessageBubble(message: Message) {
fun MessageBubble(message: Message, onEdit: () -> Unit = {}, onDelete: () -> Unit = {}) {
var expanded by remember { mutableStateOf(false) }
var confirmationDialogShown by remember { mutableStateOf(false) }

Row(
modifier = Modifier
.fillMaxWidth()
Expand All @@ -252,12 +306,63 @@ fun MessageBubble(message: Message) {
color = Color.White,
)
}
if (message.clientId == randomClientId) {
Box {
IconButton(onClick = { expanded = true }) {
Icon(Icons.Default.MoreVert, contentDescription = "More Options")
}

DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
) {
DropdownMenuItem(
text = { Text("Edit") },
onClick = {
expanded = false
onEdit()
},
)
DropdownMenuItem(
text = { Text("Delete") },
onClick = {
expanded = false
confirmationDialogShown = true
},
)
}
}
}
// Delete Confirmation Dialog
if (confirmationDialogShown) {
AlertDialog(
onDismissRequest = { confirmationDialogShown = false },
title = { Text("Delete Message") },
text = { Text("Are you sure you want to delete this message?") },
confirmButton = {
Button(
onClick = {
onDelete()
confirmationDialogShown = false
},
) {
Text("Delete")
}
},
dismissButton = {
Button(onClick = { confirmationDialogShown = false }) {
Text("Cancel")
}
},
)
}
}
}

@Composable
fun ChatInputField(
sending: Boolean = false,
updating: Boolean = false,
messageInput: TextFieldValue,
onMessageChange: (TextFieldValue) -> Unit,
onSendClick: () -> Unit,
Expand All @@ -279,14 +384,18 @@ fun ChatInputField(
.background(Color.White),
placeholder = { Text("Type a message...") },
)
if (messageInput.text.isNotEmpty()) {
Button(enabled = !sending, onClick = onSendClick) {
Text("Send")
when {
updating -> Button(enabled = !sending, onClick = onSendClick) {
Text("Update")
}
} else {
Button(onClick = onReactionClick) {

messageInput.text.isEmpty() -> Button(onClick = onReactionClick) {
Text("\uD83D\uDC4D")
}

else -> Button(enabled = !sending, onClick = onSendClick) {
Text("Send")
}
}
}
}
Expand Down
Binary file modified images/example-app-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8c27173

Please sign in to comment.