Kotlin

チャットイベント

先にVonage CLIで会話を作成し、その会話に2人のユーザーを追加しました。会話はユーザが通信する方法です。会話についての詳細は Conversation API ドキュメント.チャットイベント ConversationEvent オブジェクトは、あなたが作成した会話を使って送信されるので、チャットイベントを取得するには、まず会話に参加する必要があります。これを実装するには ChatViewModel クラスである。

を追加する。 getMemberIDIfNeeded 関数である:

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

これは memberID会話に参加するときに生成される「会話に参加する」がまだ設定されていない場合は、「会話に参加する」を呼び出します。設定されていない場合は getMemberID.作成する 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() ?: ""
        }
    }
}

この関数は、まずこのユーザーのメンバーIDを getConversationMemberもし失敗すれば、次のように会話に加わる。 joinConversation これはメンバーIDを返す。

これで、そのユーザーが会話のメンバーであることが保証されたので、クライアントを使用して会話イベントを取得することができます。という関数を作成します。 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 会話IDと GetConversationEventsParameters.パラメータにより、イベントの返し方をカスタマイズすることができます。この関数は、ページ分割されたレスポンスを返します。ページ分割についての詳細は ページネーションガイド.イベントを表示するには、イベント・オブジェクトを表示文字列に変換するヘルパー関数を作成する:

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

このチュートリアルで使用する3つのイベントは次のとおりです。 MemberJoinedConversationEvent, MemberLeftConversationEventそして MessageTextEvent.の場合 MessageTextEvent この関数は memberID プロパティを使用して、現在のログイン・ユーザーによって送信されたメッセージかどうかを判断します。これにより、UIはユーザが送信したメッセージを右に、受信したメッセージを左に固定することができます。

について ConversationEventListener

アプリケーションは、最初にロードした後、会話のイベントに反応する必要があります。 ConversationEventListener.セッションが作成されたら、このリスナーを設定するようにログインメソッドを更新する:

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

新しいイベントが受信されると、それは events これは自動的にパブリッシュされるので、UIは更新される。

UIの更新

今は ChatViewModel で、新しい会話イベントを取得してリッスンし、それらを表示するためにビューコードを更新することができます。 MainActivity.kt を更新する。 ChatScreen コンポーザブル:

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

今は LazyColumn はイベントリストを受け取り Text 要素と呼ぶ。 generateDisplayText を追加して、表示するテキストと、そのイベントがログインしているユーザーによって所有されているかどうかを取得します。最後に runBlocking ブロックでメンバーIDを取得し、ビューが最初にロードされたときに会話イベントを取得します。