Swift

Eventos de chat

Anteriormente creaste una conversación en la CLI de Vonage y agregaste los dos usuarios a esa conversación. Las conversaciones son la forma en que se comunicarán los usuarios. Puedes obtener más información sobre las conversaciones en la sección Documentación de la Conversation API. Eventos de chat, o VGConversationEvent se envían utilizando la conversación que has creado, por lo que para obtener el evento de chat primero tendrás que unirte a la conversación. Para implementar esto, actualiza la directiva ChatViewModel clase.

Añada el getMemberIDIfNeeded función:

@MainActor
final class ChatViewModel: NSObject, ObservableObject {
    ...
    
    func getMemberIDIfNeeded() async {
        guard memberID == nil else { return }
        await getMemberID()
    }   
}

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

@MainActor
final class ChatViewModel: NSObject, ObservableObject {
    ...
    
    private func getMemberID() async {
        let member = try? await client.getConversationMember(conversationID, memberId: "me")
        memberID = member?.id
        
        if memberID == nil {
            memberID = try? await client.joinConversation(conversationID)
        }
    }
}

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

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:

@MainActor
final class ChatViewModel: NSObject, ObservableObject {
    ...
    func getConversationEvents() async {
        let params = VGGetConversationEventsParameters(order: .asc, pageSize: 100)
        let eventsPage = try? await client.getConversationEvents(conversationID, parameters: params)
        self.events = eventsPage?.events ?? []
    }
}

getConversationEvents toma un ID de conversación y VGGetConversationEventsParameters. 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, cree una función de ayuda que convierta los objetos de evento en una cadena de visualización:

@MainActor
final class ChatViewModel: NSObject, ObservableObject {
    ...
    func generateDisplayText(_ event: VGPersistentConversationEvent) -> (body: String, isUser: Bool) {
        var from = "System"
        
        switch event.kind {
        case .memberJoined:
            let memberJoinedEvent = event as! VGMemberJoinedEvent
            from = memberJoinedEvent.body.user.name
            return ("\(from) joined", false)
        case .memberLeft:
            let memberLeftEvent = event as! VGMemberLeftEvent
            from = memberLeftEvent.body.user.name
            return ("\(from) left", false)
        case .messageText:
            let messageTextEvent = event as! VGMessageTextEvent
            var isUser = false
            
            if let userInfo = messageTextEvent.from as? VGEmbeddedInfo {
                isUser = userInfo.memberId == memberID
                from = isUser ? "" : "\(userInfo.user.name): "
            }
            
            return ("\(from) \(messageTextEvent.body.text)", isUser)
        default:
            return ("", false)
        }
    }
}

Los tres eventos que se utilizan en este tutorial son memberJoined, memberLefty messageText. En el caso de messageText 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.

En VGChatClientDelegate

La aplicación también necesita reaccionar a eventos en una conversación después de cargar inicialmente por lo que necesita implementar la función VGChatClientDelegate didReceiveConversationEvent evento.

extension ChatViewModel: VGChatClientDelegate {
    nonisolated func chatClient(_ client: VGChatClient, didReceiveConversationEvent event: VGConversationEvent) {
        Task { @MainActor in
            self.events.append(event as! VGPersistentConversationEvent)
        }
    }
    
    nonisolated func client(_ client: VGBaseClient, didReceiveSessionErrorWith reason: VGSessionErrorReason) {}
}

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:

struct ChatView: View {
    @StateObject var chatViewModel: ChatViewModel
    @State private var message: String = ""
    
    var body: some View {
        VStack {
            if chatViewModel.events.isEmpty {
                ProgressView()
            } else {
                VStack {
                    List {
                        ForEach(chatViewModel.events, id: \.id) { event in
                            switch event.kind {
                            case .memberJoined, .memberLeft:
                                let displayText = chatViewModel.generateDisplayText(event)
                                Text(displayText.body)
                                    .frame(maxWidth: .infinity, alignment: .center)
                            case.messageText:
                                let displayText = chatViewModel.generateDisplayText(event)
                                Text(displayText.body)
                                    .frame(maxWidth: .infinity, alignment: displayText.isUser ? .trailing : .leading)
                            default:
                                EmptyView()
                            }
                        }.listRowSeparator(.hidden)
                    }.listStyle(.plain)
                    
                    Spacer()
                    
                    HStack {
                        TextField("Message", text: $message)
                        Button("Send") {
                            Task {
                                
                            }
                        }.buttonStyle(.bordered)
                    }.padding(8)
                }
            }
        }.onAppear {
            Task {
                await chatViewModel.getMemberIDIfNeeded()
                await chatViewModel.getConversationEvents()
            }
        }
    }
}

Ahora en el Listse ha actualizado la sentencia switch para llamar a generateDisplayText para los tres tipos diferentes de eventos de conversación que utiliza el tutorial. También hay un ProgressView para cuando el ChatViewModel se está cargando. Cuando se carga la vista, onAppear que llama a las funciones creadas en el archivo ChatViewModel.

Construir y ejecutar

Pulse Cmd + R para construir y ejecutar de nuevo. Después de iniciar sesión verás que Alice se ha unido a la conversación:

Chat interface with connection events