Kotlin

Eventos de chat

Anteriormente, creaste una conversación en la CLI de Vonage y añadiste a los dos usuarios a dicha conversación. Las conversaciones son el medio a través del cual se comunicarán los usuarios. Puedes obtener más información sobre las conversaciones en la Documentación de la Conversation API. Eventos de chat, o ConversationEvent Los objetos se envían a través de la conversación que has creado, por lo que, para recibir eventos de chat, primero tendrás que unirte a la conversación. Para implementar esto, actualiza el ChatViewModel clase.

Añade el getMemberIDIfNeeded función:

class ChatViewModel(application: Application) : AndroidViewModel(application = application) {
    private var memberID = "" 
    ...
    
    suspend fun getMemberIDIfNeeded(){
        if(memberID.isNotEmpty()) return else getMemberID()
    }
}

Esto comprobará si el memberIDque se genera cuando te unes a una conversación. Si no es así, llama a getMemberID. Cree getMemberID:

class ChatViewModel(application: Application) : AndroidViewModel(application = application) {
    ...
    
    private suspend fun getMemberID() {
        try {
            val member = client.getConversationMember(conversationID,  "me")
            memberID = member.id
        }
        catch (e: VGError) {
            //User not yet a member of the conversation
            memberID = client.joinConversation(conversationID)
        }
        catch (err:Error) {
            isError = true
            error = err.localizedMessage?.toString() ?: ""
        }
    }
}

Esta función intenta obtener primero el ID de miembro de este usuario mediante getConversationMembersi falla, se unirá a la conversación con joinConversation que devuelve el ID de socio.

Ahora que está garantizado que ese usuario es miembro de la conversación, puedes obtener los eventos de la conversación utilizando el cliente. Crea una función llamada getConversationEvents:

class ChatViewModel(application: Application) : AndroidViewModel(application = application) {
    ...
    suspend fun getConversationEvents(){
        val params = GetConversationEventsParameters(PresentingOrder.ASC,100)
        try {
            val eventsPage = client.getConversationEvents(conversationID, params)
            events.clear()
            events.addAll(eventsPage.events.toMutableStateList())
        }
        catch (err:Error) {
            isError = true
            error = err.localizedMessage?.toString() ?: ""
        }
    }
}

getConversationEvents toma un identificador de conversación y GetConversationEventsParameters. Los parámetros le permiten personalizar la forma en que se le devuelven los eventos. Esta función devuelve una respuesta paginada. Para obtener más información sobre la paginación, puede leer el documento guía de paginación. Para mostrar los eventos, crea una función auxiliar que convierta los objetos de evento en una cadena de visualización:

class ChatViewModel(application: Application) : AndroidViewModel(application = application) {
    ...
    fun generateDisplayedText(event: PersistentConversationEvent): Pair<String, Boolean>{
        var from = "System"
        return when(event){
            is MemberJoinedConversationEvent -> {
                val from = event.body.user.name
                "$from joined" to false
            }
            is MemberLeftConversationEvent -> {
                val from = event.body.user.name
                "$from left" to false
            }
            is MessageTextEvent -> {
                var isUser = false
                val userInfo = event.from as EmbeddedInfo
                isUser = userInfo.memberId == memberID
                from = if(isUser) "" else "${userInfo.user.name}: "
                "$from ${event.body.text}" to isUser
            }
            else -> {
                "" to false
            }
        }
    }
}

Los tres eventos que se utilizan en este tutorial son MemberJoinedConversationEvent, MemberLeftConversationEventy MessageTextEvent. En el caso de MessageTextEvent La función utiliza el memberID para determinar si el mensaje fue enviado por el usuario actual. Esto permitirá a la interfaz de usuario fijar los mensajes enviados por los usuarios a la derecha y los mensajes recibidos a la izquierda.

El ConversationEventListener

La aplicación también necesita reaccionar a eventos en una conversación después de la carga inicial, por lo que necesita implementar una función ConversationEventListener. Actualiza tu método de inicio de sesión para configurar este listener una vez creada la sesión, de la siguiente manera:

    fun login(username: String) {
        val jwt = if(username == "Alice") aliceJwt else bobJwt
        client.createSession(jwt) { err, sessionId ->
            when {
                err != null -> {
                    isError = true
                    error = err.localizedMessage?.toString() ?: ""
                }
                else -> {
                    client.setOnConversationEventListener {
                        events.add(it as PersistentConversationEvent)
                    }
                    isLoggedIn = true
                }
            }
        }
    }

Cuando se recibe un nuevo evento, éste se añade al archivo events que se publica automáticamente para que la interfaz de usuario se actualice.

Actualizar la interfaz de usuario

Ahora que el ChatViewModel puede recuperar y escuchar nuevos eventos de conversación, actualizar el código de la vista para mostrarlos, en MainActivity.kt Actualizar el ChatScreen Componible:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ChatScreen() {
    val vm = LocalChatState.current
    var text by remember { mutableStateOf("") }

    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Bottom
    ) {
        LazyColumn(
            modifier = Modifier.fillMaxWidth()
        ) {
            items(vm.events) { event ->
                val (text, isUser) = vm.generateDisplayedText(event)
                val textAlightment = if (isUser) TextAlign.Right else TextAlign.Left
                val textColor = if (isUser) Color.Blue else Color.Black
                Text(
                    text = text,
                    fontSize = 20.sp,
                    textAlign = textAlightment,
                    color = textColor
                )
            }
        }
        Row(){
            TextField(
                value = text,
                onValueChange = { text = it },
                label = { Text("Message") }
            )
            Button(onClick = {}
            }) {
                Text("Send")
            }
        }
    }

    runBlocking {
        vm.getMemberIDIfNeeded()
        vm.getConversationEvents()
    }
}

Ahora el LazyColumn tomará la lista de eventos y generará un Text para cada uno, aquí llamamos generateDisplayText para obtener el texto a mostrar, y si ese evento pertenece al usuario conectado o no. Finalmente añadimos un runBlocking para obtener el id de miembro y luego obtener los eventos de conversación cuando la vista se carga por primera vez.