More work related to IMDNs display & chat in general

This commit is contained in:
Sylvain Berfini 2023-10-19 12:11:57 +02:00
parent c151ef1526
commit f821707cc6
9 changed files with 101 additions and 110 deletions

View file

@ -183,7 +183,11 @@ class ConversationFragment : GenericFragment() {
adapter.showDeliveryForChatMessageModelEvent.observe(viewLifecycleOwner) {
it.consume { model ->
showDeliveryBottomSheetDialog(model)
if (viewModel.isGroup.value == true) {
showDeliveryBottomSheetDialog(model)
} else {
Log.w("$TAG Conversation is not a group, not showing delivery bottom sheet")
}
}
}

View file

@ -6,6 +6,7 @@ import androidx.lifecycle.MutableLiveData
import org.linphone.R
import org.linphone.core.ChatMessage
import org.linphone.core.ChatMessage.State
import org.linphone.core.tools.Log
import org.linphone.utils.AppUtils
class ChatMessageDeliveryModel @WorkerThread constructor(
@ -58,45 +59,80 @@ class ChatMessageDeliveryModel @WorkerThread constructor(
@WorkerThread
private fun computeDeliveryStatus() {
for (participant in chatMessage.getParticipantsByImdnState(State.Displayed)) {
displayedModels.add(ChatMessageParticipantDeliveryModel(participant))
displayedModels.add(
ChatMessageParticipantDeliveryModel(
participant.participant.address,
participant.stateChangeTime
)
)
}
// Always add ourselves to prevent empty list
displayedModels.add(
ChatMessageParticipantDeliveryModel(
chatMessage.localAddress,
chatMessage.time
)
)
val readCount = displayedModels.size.toString()
readLabel.postValue(
AppUtils.getFormattedString(
R.string.message_delivery_info_read_title,
displayedModels.size.toString()
readCount
)
)
for (participant in chatMessage.getParticipantsByImdnState(State.DeliveredToUser)) {
deliveredModels.add(ChatMessageParticipantDeliveryModel(participant))
deliveredModels.add(
ChatMessageParticipantDeliveryModel(
participant.participant.address,
participant.stateChangeTime
)
)
}
val receivedCount = deliveredModels.size.toString()
receivedLabel.postValue(
AppUtils.getFormattedString(
R.string.message_delivery_info_received_title,
deliveredModels.size.toString()
receivedCount
)
)
for (participant in chatMessage.getParticipantsByImdnState(State.Delivered)) {
sentModels.add(ChatMessageParticipantDeliveryModel(participant))
sentModels.add(
ChatMessageParticipantDeliveryModel(
participant.participant.address,
participant.stateChangeTime
)
)
}
val sentCount = sentModels.size.toString()
sentLabel.postValue(
AppUtils.getFormattedString(
R.string.message_delivery_info_sent_title,
sentModels.size.toString()
sentCount
)
)
for (participant in chatMessage.getParticipantsByImdnState(State.NotDelivered)) {
errorModels.add(ChatMessageParticipantDeliveryModel(participant))
errorModels.add(
ChatMessageParticipantDeliveryModel(
participant.participant.address,
participant.stateChangeTime
)
)
}
val errorCount = errorModels.size.toString()
errorLabel.postValue(
AppUtils.getFormattedString(
R.string.message_delivery_info_error_title,
errorModels.size.toString()
errorCount
)
)
deliveryModels.postValue(displayedModels)
Log.i("$TAG Message ID [${chatMessage.messageId}] is in state [${chatMessage.state}]")
Log.i(
"$TAG There are [$readCount] that have read this message, [$receivedCount] that have received it, [$sentCount] that haven't received it yet and [$errorCount] that probably won't receive it due to an error"
)
}
}

View file

@ -23,7 +23,6 @@ import androidx.annotation.UiThread
import androidx.annotation.WorkerThread
import androidx.lifecycle.MutableLiveData
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.R
import org.linphone.core.Address
import org.linphone.core.ChatMessage
import org.linphone.core.ChatMessageListenerStub
@ -66,7 +65,7 @@ class ChatMessageModel @WorkerThread constructor(
private val chatMessageListener = object : ChatMessageListenerStub() {
@WorkerThread
override fun onMsgStateChanged(message: ChatMessage, messageState: ChatMessage.State?) {
computeStatusIcon(chatMessage.state)
statusIcon.postValue(LinphoneUtils.getChatIconResId(chatMessage.state))
}
@WorkerThread
@ -84,7 +83,7 @@ class ChatMessageModel @WorkerThread constructor(
init {
chatMessage.addListener(chatMessageListener)
computeStatusIcon(chatMessage.state)
statusIcon.postValue(LinphoneUtils.getChatIconResId(chatMessage.state))
}
@WorkerThread
@ -101,26 +100,4 @@ class ChatMessageModel @WorkerThread constructor(
dismissLongPressMenuEvent.postValue(Event(true))
}
}
@WorkerThread
private fun computeStatusIcon(state: ChatMessage.State) {
val icon = when (state) {
ChatMessage.State.Displayed -> {
R.drawable.checks
}
ChatMessage.State.DeliveredToUser -> {
R.drawable.check
}
ChatMessage.State.Delivered -> {
R.drawable.envelope_simple
}
ChatMessage.State.NotDelivered -> {
R.drawable.warning_circle
}
else -> {
R.drawable.in_progress
}
}
statusIcon.postValue(icon)
}
}

View file

@ -1,18 +1,15 @@
package org.linphone.ui.main.chat.model
import androidx.annotation.WorkerThread
import org.linphone.LinphoneApplication
import org.linphone.core.ParticipantImdnState
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.core.Address
import org.linphone.utils.TimestampUtils
class ChatMessageParticipantDeliveryModel @WorkerThread constructor(
imdnState: ParticipantImdnState
address: Address,
timestamp: Long
) {
val address = imdnState.participant.address
val avatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(address)
val avatarModel = LinphoneApplication.coreContext.contactsManager.getContactAvatarModelForAddress(
address
)
val time = TimestampUtils.toString(imdnState.stateChangeTime)
val time = TimestampUtils.toString(timestamp)
}

View file

@ -228,32 +228,7 @@ class ConversationModel @WorkerThread constructor(private val chatRoom: ChatRoom
val isOutgoing = message.isOutgoing
isLastMessageOutgoing.postValue(isOutgoing)
if (isOutgoing) {
val icon = when (message.state) {
ChatMessage.State.Displayed -> {
R.drawable.checks
}
ChatMessage.State.DeliveredToUser -> {
R.drawable.check
}
ChatMessage.State.Delivered -> {
R.drawable.sent
}
ChatMessage.State.InProgress, ChatMessage.State.FileTransferInProgress -> {
R.drawable.in_progress
}
ChatMessage.State.NotDelivered, ChatMessage.State.FileTransferError -> {
R.drawable.warning_circle
}
else -> {
R.drawable.info
}
}
lastMessageIcon.postValue(icon)
lastMessageIcon.postValue(LinphoneUtils.getChatIconResId(message.state))
}
}

View file

@ -262,7 +262,7 @@ class ConversationInfoViewModel @UiThread constructor() : ViewModel() {
isMyselfAdmin.postValue(chatRoom.me?.isAdmin)
val isGroupChatRoom = isChatRoomAGroup()
val isGroupChatRoom = LinphoneUtils.isChatRoomAGroup(chatRoom)
isGroup.postValue(isGroupChatRoom)
val empty = chatRoom.hasCapability(ChatRoom.Capabilities.Conference.toInt()) && chatRoom.participants.isEmpty()
@ -279,8 +279,8 @@ class ConversationInfoViewModel @UiThread constructor() : ViewModel() {
@WorkerThread
private fun computeParticipantsList() {
val groupChatRoom = isChatRoomAGroup()
val selfAdmin = chatRoom.me?.isAdmin == true
val groupChatRoom = LinphoneUtils.isChatRoomAGroup(chatRoom)
val selfAdmin = if (groupChatRoom) chatRoom.me?.isAdmin == true else false
val friends = arrayListOf<Friend>()
val participantsList = arrayListOf<ParticipantModel>()
@ -315,13 +315,4 @@ class ConversationInfoViewModel @UiThread constructor() : ViewModel() {
participants.postValue(participantsList)
}
@WorkerThread
private fun isChatRoomAGroup(): Boolean {
return if (::chatRoom.isInitialized) {
LinphoneUtils.isChatRoomAGroup(chatRoom)
} else {
false
}
}
}

View file

@ -98,7 +98,15 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
} else {
false
}
list.add(EventLogModel(eventLog, avatarModel, isChatRoomAGroup(), group, true))
list.add(
EventLogModel(
eventLog,
avatarModel,
LinphoneUtils.isChatRoomAGroup(chatRoom),
group,
true
)
)
events.postValue(list)
}
@ -277,7 +285,7 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
Log.w("$TAG Chat room with subject [${chatRoom.subject}] is read only!")
}
val group = isChatRoomAGroup()
val group = LinphoneUtils.isChatRoomAGroup(chatRoom)
isGroup.postValue(group)
subject.postValue(chatRoom.subject)
@ -324,6 +332,7 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
private fun processGroupedEvents(
groupedEventLogs: ArrayList<EventLog>
): ArrayList<EventLogModel> {
val groupChatRoom = LinphoneUtils.isChatRoomAGroup(chatRoom)
val eventsList = arrayListOf<EventLogModel>()
// Handle all events in group, then re-start a new group with current item
@ -335,7 +344,7 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
val model = EventLogModel(
groupedEvent,
avatar,
isChatRoomAGroup(),
groupChatRoom,
index > 0,
index == groupedEventLogs.size - 1
)
@ -434,13 +443,4 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
composingLabel.postValue("")
}
}
@WorkerThread
private fun isChatRoomAGroup(): Boolean {
return if (::chatRoom.isInitialized) {
LinphoneUtils.isChatRoomAGroup(chatRoom)
} else {
false
}
}
}

View file

@ -185,6 +185,31 @@ class LinphoneUtils {
}
}
@AnyThread
@IntegerRes
fun getChatIconResId(chatState: ChatMessage.State): Int {
return when (chatState) {
ChatMessage.State.Displayed -> {
R.drawable.checks
}
ChatMessage.State.DeliveredToUser -> {
R.drawable.check
}
ChatMessage.State.Delivered -> {
R.drawable.envelope_simple
}
ChatMessage.State.InProgress, ChatMessage.State.FileTransferInProgress -> {
R.drawable.in_progress
}
ChatMessage.State.NotDelivered, ChatMessage.State.FileTransferError -> {
R.drawable.warning_circle
}
else -> {
R.drawable.not_trusted
}
}
}
@WorkerThread
fun getChatRoomId(room: ChatRoom): String {
return getChatRoomId(room.localAddress, room.peerAddress)
@ -206,8 +231,9 @@ class LinphoneUtils {
@WorkerThread
fun isChatRoomAGroup(chatRoom: ChatRoom): Boolean {
return !chatRoom.hasCapability(ChatRoom.Capabilities.OneToOne.toInt()) &&
chatRoom.hasCapability(ChatRoom.Capabilities.Conference.toInt())
val oneToOne = chatRoom.hasCapability(ChatRoom.Capabilities.OneToOne.toInt())
val conference = chatRoom.hasCapability(ChatRoom.Capabilities.Conference.toInt())
return !oneToOne && conference
}
@WorkerThread

View file

@ -1,15 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="22dp"
android:height="20dp"
android:viewportWidth="22"
android:viewportHeight="20">
<path
android:pathData="M17.808,0.5H1.192C1.009,0.5 0.833,0.573 0.703,0.703C0.573,0.833 0.5,1.009 0.5,1.192V12.962C0.5,13.329 0.646,13.681 0.906,13.941C1.165,14.2 1.517,14.346 1.885,14.346H17.115C17.483,14.346 17.835,14.2 18.094,13.941C18.354,13.681 18.5,13.329 18.5,12.962V1.192C18.5,1.009 18.427,0.833 18.297,0.703C18.167,0.573 17.991,0.5 17.808,0.5ZM16.028,1.885L9.5,7.869L2.972,1.885H16.028ZM17.115,12.962H1.885V2.766L9.032,9.318C9.16,9.436 9.327,9.501 9.5,9.501C9.673,9.501 9.84,9.436 9.968,9.318L17.115,2.766V12.962Z"
android:fillColor="#FE5E00"/>
<path
android:pathData="M15.5,13.5m-6,0a6,6 0,1 1,12 0a6,6 0,1 1,-12 0"
android:fillColor="#ffffff"/>
<path
android:pathData="M15.5,8.5C14.511,8.5 13.544,8.793 12.722,9.343C11.9,9.892 11.259,10.673 10.881,11.587C10.502,12.5 10.403,13.505 10.596,14.476C10.789,15.445 11.265,16.336 11.965,17.035C12.664,17.735 13.555,18.211 14.524,18.404C15.495,18.597 16.5,18.498 17.413,18.119C18.327,17.741 19.108,17.1 19.657,16.278C20.207,15.456 20.5,14.489 20.5,13.5C20.499,12.174 19.971,10.903 19.034,9.966C18.097,9.029 16.826,8.501 15.5,8.5ZM17.695,13.772L16.157,15.311C16.085,15.383 15.987,15.423 15.885,15.423C15.783,15.423 15.685,15.383 15.613,15.311C15.54,15.238 15.5,15.141 15.5,15.038C15.5,14.936 15.54,14.839 15.613,14.766L16.495,13.885H13.577C13.475,13.885 13.377,13.844 13.305,13.772C13.233,13.7 13.192,13.602 13.192,13.5C13.192,13.398 13.233,13.3 13.305,13.228C13.377,13.156 13.475,13.115 13.577,13.115H16.495L15.613,12.234C15.54,12.161 15.5,12.064 15.5,11.962C15.5,11.859 15.54,11.762 15.613,11.689C15.685,11.617 15.783,11.577 15.885,11.577C15.987,11.577 16.085,11.617 16.157,11.689L17.695,13.228C17.731,13.264 17.759,13.306 17.779,13.353C17.798,13.399 17.808,13.45 17.808,13.5C17.808,13.55 17.798,13.601 17.779,13.647C17.759,13.694 17.731,13.736 17.695,13.772Z"
android:fillColor="#FE5E00"/>
</vector>