Swift

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 VGConversationEvent 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:

@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 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:

@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 identificador 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, crea una función auxiliar 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.

El VGChatClientDelegate

La aplicación también debe reaccionar ante los eventos que se produzcan en una conversación una vez que se haya cargado por primera vez, por lo que debes implementar el 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 Para poder recuperar y detectar nuevos eventos de conversación, actualiza 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 porque 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 compilarlo y ejecutarlo de nuevo. Una vez que hayas iniciado sesión, verás que Alice se ha unido a la conversación:

Chat interface with connection events