Kotlin

Eventos de bate-papo

Anteriormente, você criou uma conversa na CLI da Vonage e adicionou os dois usuários a essa conversa. As conversas são o meio pelo qual os usuários se comunicarão. Você pode saber mais sobre conversas na Documentação da Conversation API. Eventos de bate-papo, ou ConversationEvent Os objetos são enviados por meio da conversa que você criou; portanto, para receber eventos de chat, primeiro você precisará entrar na conversa. Para implementar isso, atualize o ChatViewModel classe.

Adicione o getMemberIDIfNeeded função:

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

Isso verificará se o memberID, que é gerado quando você entra em uma conversa, ainda não foi definido. Caso contrário, ele chama getMemberID. Criar 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() ?: ""
        }
    }
}

Essa função tenta, em primeiro lugar, obter o ID de membro desse usuário com getConversationMember, se não der certo, ele entrará na conversa com joinConversation que retorna o ID do membro.

Agora que se tem a certeza de que esse usuário faz parte da conversa, você pode obter os eventos da conversa usando o cliente. Crie uma função chamada 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 recebe um ID de conversa e GetConversationEventsParameters. Os parâmetros permitem que você personalize a forma como os eventos são exibidos. Essa função retorna uma resposta paginada. Para saber mais sobre paginação, você pode ler o guia de paginação. Para exibir os eventos, crie uma função auxiliar que transforme os objetos de evento em uma string de exibição:

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
            }
        }
    }
}

Os três eventos utilizados neste tutorial são MemberJoinedConversationEvent, MemberLeftConversationEvent, e MessageTextEvent. No caso de MessageTextEvent a função utiliza o memberID propriedade para determinar se a mensagem foi enviada pelo usuário atualmente conectado. Isso permitirá que a interface do usuário fixe as mensagens enviadas pelo usuário à direita e as mensagens recebidas à esquerda.

O ConversationEventListener

O aplicativo também precisa reagir aos eventos que ocorrem em uma conversa após o carregamento inicial; portanto, é necessário implementar um ConversationEventListener. Atualize seu método de login para definir esse ouvinte assim que a sessão for criada, da seguinte forma:

    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
                }
            }
        }
    }

Quando um novo evento é recebido, ele é anexado à events que é publicado automaticamente, de modo que a interface do usuário seja atualizada.

Atualização da interface do usuário

Agora que o ChatViewModel é possível recuperar e monitorar novos eventos de conversa, atualizar o código da visualização para exibi-los, em MainActivity.kt Atualize o ChatScreen Componível:

@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()
    }
}

Agora, o LazyColumn pega a lista de eventos e gera um Text elemento para cada um; aqui, chamamos de generateDisplayText para que o texto seja exibido e para verificar se esse evento pertence ou não ao usuário conectado. Por fim, adicionamos um runBlocking bloco para obter o ID do membro e, em seguida, recuperar os eventos de conversa assim que a visualização for carregada pela primeira vez.