[Chat] user added/removed messages from service events (#542)

This commit is contained in:
Adam Hammer 2022-10-25 13:15:37 -07:00 коммит произвёл GitHub
Родитель 2b23425126
Коммит 2ece7bd9f8
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 97 добавлений и 30 удалений

Просмотреть файл

@ -15,6 +15,7 @@ internal data class MessageInfoModel(
val internalId: String? = null,
val messageType: ChatMessageType?,
val content: String?,
val topic: String? = null,
val participants: List<String> = emptyList(),
val version: String? = null,
val senderDisplayName: String? = null,
@ -30,6 +31,7 @@ internal fun com.azure.android.communication.chat.models.ChatMessage.into(): Mes
id = this.id,
messageType = this.type.into(),
content = this.content.message,
topic = this.content.topic,
participants = this.content.participants?.map { it.displayName }?.toList() ?: emptyList(),
internalId = null,
version = this.version,

Просмотреть файл

@ -15,9 +15,9 @@ internal data class ChatCompositeColors(
val textColor: Color = Color(0xFF212121),
val outlineColor: Color = Color(0xFFE1E1E1),
val messageBackground: Color = Color(0xFFF1F1F1),
val systemIconColor: Color = Color(0xFF919191),
val messageBackgroundSelf: Color = Color(0xFFDEECF9),
)
internal val ChatCompositeColorPalette = staticCompositionLocalOf {
ChatCompositeColors()
}

Просмотреть файл

@ -17,6 +17,7 @@ internal data class ChatCompositeDimensions(
val messageAvatarSize: Dp = 24.dp,
val messageUsernamePaddingEnd: Dp = 8.dp,
val messagePadding: PaddingValues = PaddingValues(start = 10.dp, end = 10.dp, top = 8.dp, bottom = 8.dp),
val systemMessagePadding: PaddingValues = PaddingValues(start = 20.dp, end = 5.dp, top = 10.dp, bottom = 10.dp),
val typingIndicatorAreaHeight: Dp = 36.dp,
val dateHeaderPadding: PaddingValues = PaddingValues(start = 0.dp, end = 0.dp, top = 16.dp, bottom = 0.dp)
)

Просмотреть файл

@ -15,14 +15,17 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.text.BasicText
import androidx.compose.material.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.text.HtmlCompat
import com.azure.android.communication.ui.chat.R
import com.azure.android.communication.ui.chat.presentation.style.ChatCompositeTheme
import com.azure.android.communication.ui.chat.presentation.ui.viewmodel.MessageViewModel
import com.azure.android.communication.ui.chat.presentation.ui.viewmodel.toViewModelList
@ -54,16 +57,27 @@ internal fun MessageView(viewModel: MessageViewModel) {
)
}
}
when (viewModel.message.messageType) {
ChatMessageType.TEXT -> BasicChatMessage(viewModel)
ChatMessageType.HTML -> BasicChatMessage(viewModel)
ChatMessageType.TOPIC_UPDATED -> BasicText("Topic Updated")
ChatMessageType.PARTICIPANT_ADDED -> UserJoinedMessage(viewModel)
ChatMessageType.PARTICIPANT_REMOVED -> UserLeftMessage(viewModel)
ChatMessageType.TOPIC_UPDATED -> SystemMessage(
icon = R.drawable.azure_communication_ui_chat_ic_participant_removed_filled, /* TODO: update icon */
stringResource = R.string.azure_communication_ui_chat_topic_updated,
substitution = listOf(viewModel.message.topic ?: "Unknown")
)
ChatMessageType.PARTICIPANT_ADDED -> SystemMessage(
icon = R.drawable.azure_communication_ui_chat_ic_participant_added_filled,
stringResource = R.string.azure_communication_ui_chat_joined_chat,
substitution = viewModel.message.participants
)
ChatMessageType.PARTICIPANT_REMOVED -> SystemMessage(
icon = R.drawable.azure_communication_ui_chat_ic_participant_removed_filled,
stringResource = R.string.azure_communication_ui_chat_left_chat,
substitution = viewModel.message.participants
)
else -> {
BasicText(
text = "${viewModel.message.content} !TYPE NOT DETECTED!"
text = "${viewModel.message.content} !TYPE NOT DETECTED!" ?: "Empty"
)
}
}
@ -71,32 +85,19 @@ internal fun MessageView(viewModel: MessageViewModel) {
}
@Composable
private fun UserJoinedMessage(viewModel: MessageViewModel) {
if (viewModel.message.participants.size <= 1) {
BasicText(
"${viewModel.message.participants.firstOrNull() ?: "Unknown"} joined the chat",
style = ChatCompositeTheme.typography.systemMessage
)
} else {
BasicText(
"${viewModel.message.participants.joinToString(", ")} joined the chat",
style = ChatCompositeTheme.typography.systemMessage
)
}
}
private fun SystemMessage(icon: Int, stringResource: Int, substitution: List<String>) {
@Composable
private fun UserLeftMessage(viewModel: MessageViewModel) {
if (viewModel.message.participants.size <= 1) {
BasicText(
"${viewModel.message.participants.firstOrNull() ?: "Unknown"} left the chat",
style = ChatCompositeTheme.typography.systemMessage
)
} else {
BasicText(
"${viewModel.message.participants.joinToString(", ")} left the chat",
style = ChatCompositeTheme.typography.systemMessage
val text = LocalContext.current.getString(stringResource, substitution.joinToString(", "))
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
painter = painterResource(id = icon),
contentDescription = "Participant Added",
modifier = Modifier.padding(
ChatCompositeTheme.dimensions.systemMessagePadding
),
tint = ChatCompositeTheme.colors.systemIconColor
)
BasicText(text = text, style = ChatCompositeTheme.typography.systemMessage)
}
}

Просмотреть файл

@ -3,16 +3,20 @@
package com.azure.android.communication.ui.chat.redux.middleware.repository
import com.azure.android.communication.ui.chat.models.MessageInfoModel
import com.azure.android.communication.ui.chat.redux.Dispatch
import com.azure.android.communication.ui.chat.redux.Middleware
import com.azure.android.communication.ui.chat.redux.Store
import com.azure.android.communication.ui.chat.redux.action.Action
import com.azure.android.communication.ui.chat.redux.action.ChatAction
import com.azure.android.communication.ui.chat.redux.action.NetworkAction
import com.azure.android.communication.ui.chat.redux.action.ParticipantAction
import com.azure.android.communication.ui.chat.redux.action.RepositoryAction
import com.azure.android.communication.ui.chat.redux.middleware.sdk.ChatMiddleware
import com.azure.android.communication.ui.chat.redux.state.ReduxState
import com.azure.android.communication.ui.chat.repository.MessageRepositoryWriter
import com.azure.android.communication.ui.chat.service.sdk.wrapper.ChatMessageType
import org.threeten.bp.OffsetDateTime
internal interface MessageRepositoryMiddleware
@ -36,6 +40,8 @@ internal class MessageRepositoryMiddlewareImpl(
is ChatAction.MessageReceived -> processNewMessage(action, store::dispatch)
is ChatAction.MessageDeleted -> processDeletedMessage(action, store::dispatch)
is ChatAction.MessageEdited -> processEditMessage(action, store::dispatch)
is ParticipantAction.ParticipantsAdded -> processParticipantsAdded(action, store::dispatch)
is ParticipantAction.ParticipantsRemoved -> processParticipantsRemoved(action, store::dispatch)
is NetworkAction.Disconnected -> processNetworkDisconnected(store::dispatch)
}
@ -72,6 +78,42 @@ internal class MessageRepositoryMiddlewareImpl(
notifyUpdate(dispatch)
}
var skipFirstParticipantsAddedMessage = true
// Fake a message for Participant Added
private fun processParticipantsAdded(action: ParticipantAction.ParticipantsAdded, dispatch: Dispatch) {
// This comes through at start, but we don't want to pass it through
// since it's also in the historical messages
if (skipFirstParticipantsAddedMessage) {
skipFirstParticipantsAddedMessage = false
return
}
messageRepository.addLocalMessage(
MessageInfoModel(
id = "${messageRepository.getLastMessage()?.id?.toLong() ?: 0 + 1}",
participants = action.participants.map { it.displayName ?: "" },
content = null,
createdOn = OffsetDateTime.now(),
senderDisplayName = null,
messageType = ChatMessageType.PARTICIPANT_ADDED
)
)
notifyUpdate(dispatch)
}
private fun processParticipantsRemoved(action: ParticipantAction.ParticipantsRemoved, dispatch: Dispatch) {
messageRepository.addLocalMessage(
MessageInfoModel(
id = "${messageRepository.getLastMessage()?.id?.toLong() ?: 0 + 1}",
participants = action.participants.map { it.displayName ?: "" },
content = null,
createdOn = OffsetDateTime.now(),
senderDisplayName = null,
messageType = ChatMessageType.PARTICIPANT_REMOVED
)
)
notifyUpdate(dispatch)
}
private fun processDeletedMessage(action: ChatAction.MessageDeleted, dispatch: Dispatch) {
messageRepository.removeMessage(action.message)
notifyUpdate(dispatch)

Просмотреть файл

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="13dp"
android:height="14dp"
android:viewportWidth="13"
android:viewportHeight="14">
<path
android:pathData="M4.222,12.957C1.555,12.653 0,10.803 0,9L0,8.5C0,7.672 0.672,7 1.5,7H3.6C3.438,7.317 3.306,7.651 3.207,8H1.5C1.224,8 1,8.224 1,8.5V9C1,10.128 1.882,11.333 3.502,11.8C3.694,12.216 3.937,12.604 4.222,12.957ZM7.626,4.069C7.707,3.81 7.75,3.535 7.75,3.25C7.75,1.731 6.519,0.5 5,0.5C3.481,0.5 2.25,1.731 2.25,3.25C2.25,4.537 3.134,5.617 4.327,5.917C4.642,5.551 5.004,5.226 5.405,4.953C5.275,4.984 5.139,5 5,5C4.034,5 3.25,4.216 3.25,3.25C3.25,2.283 4.034,1.5 5,1.5C5.966,1.5 6.75,2.283 6.75,3.25C6.75,3.731 6.556,4.167 6.241,4.484C6.676,4.288 7.14,4.147 7.626,4.069ZM8.5,14C10.985,14 13,11.985 13,9.5C13,7.015 10.985,5 8.5,5C6.015,5 4,7.015 4,9.5C4,11.985 6.015,14 8.5,14ZM8.5,7C8.776,7 9,7.224 9,7.5V9H10.5C10.776,9 11,9.224 11,9.5C11,9.776 10.776,10 10.5,10H9V11.5C9,11.776 8.776,12 8.5,12C8.224,12 8,11.776 8,11.5V10H6.5C6.224,10 6,9.776 6,9.5C6,9.224 6.224,9 6.5,9H8L8,7.5C8,7.224 8.224,7 8.5,7Z"
android:fillColor="#919191"/>
</vector>

Просмотреть файл

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="13dp"
android:height="14dp"
android:viewportWidth="13"
android:viewportHeight="14">
<path
android:pathData="M4.222,12.957C1.555,12.653 0,10.803 0,9L0,8.5C0,7.672 0.672,7 1.5,7H3.6C3.438,7.317 3.306,7.651 3.207,8H1.5C1.224,8 1,8.224 1,8.5V9C1,10.128 1.882,11.333 3.502,11.8C3.694,12.216 3.937,12.604 4.222,12.957ZM7.626,4.069C7.707,3.81 7.75,3.535 7.75,3.25C7.75,1.731 6.519,0.5 5,0.5C3.481,0.5 2.25,1.731 2.25,3.25C2.25,4.537 3.134,5.617 4.327,5.917C4.642,5.551 5.004,5.226 5.405,4.953C5.275,4.984 5.139,5 5,5C4.034,5 3.25,4.216 3.25,3.25C3.25,2.283 4.034,1.5 5,1.5C5.966,1.5 6.75,2.283 6.75,3.25C6.75,3.731 6.556,4.167 6.241,4.484C6.676,4.288 7.14,4.147 7.626,4.069ZM13,9.5C13,11.985 10.985,14 8.5,14C6.015,14 4,11.985 4,9.5C4,7.015 6.015,5 8.5,5C10.985,5 13,7.015 13,9.5ZM6.147,9.146L6.144,9.149C6.097,9.196 6.062,9.251 6.038,9.309C6.014,9.367 6,9.43 6,9.497L6,9.5L6,9.503C6,9.57 6.014,9.633 6.038,9.691C6.062,9.75 6.099,9.806 6.146,9.854L8.146,11.854C8.342,12.049 8.658,12.049 8.854,11.854C9.049,11.658 9.049,11.342 8.854,11.146L7.707,10H10.5C10.776,10 11,9.776 11,9.5C11,9.224 10.776,9 10.5,9H7.707L8.854,7.854C9.049,7.658 9.049,7.342 8.854,7.146C8.658,6.951 8.342,6.951 8.146,7.146L6.147,9.146Z"
android:fillColor="#919191"/>
</vector>

Просмотреть файл

@ -12,6 +12,9 @@
<string name="azure_communication_ui_chat_first_name_is_typing">%1$s is typing</string>
<string name="azure_communication_ui_chat_two_names_are_typing">%1$s and %2$s are typing"</string>
<string name="azure_communication_ui_chat_three_or_more_are_typing">%1$s, %2$s and %3$d %4$s are typing</string>
<string name="azure_communication_ui_chat_joined_chat">%1$s joined the chat</string>
<string name="azure_communication_ui_chat_left_chat">%1$s left the chat</string>
<string name="azure_communication_ui_chat_topic_updated">Topic Updated: %1$s</string>
<string name="azure_communication_ui_chat_message_today">Today</string>
<string name="azure_communication_ui_chat_message_yesterday">Yesterday</string>
</resources>