Updated previous & next messages bubbles if needed when a message is deleted

This commit is contained in:
Sylvain Berfini 2023-11-29 09:11:13 +01:00
parent 99445cc8d6
commit 9070b77b30
6 changed files with 101 additions and 47 deletions

View file

@ -210,8 +210,8 @@ class ConversationEventAdapter : ListAdapter<EventLogModel, RecyclerView.ViewHol
val oldModel = (oldItem.model as MessageModel)
val newModel = (newItem.model as MessageModel)
oldModel.statusIcon.value == newModel.statusIcon.value &&
oldModel.isGroupedWithNextOne == newModel.isGroupedWithNextOne &&
oldModel.isGroupedWithPreviousOne == newModel.isGroupedWithPreviousOne
oldModel.groupedWithNextMessage.value == newModel.groupedWithNextMessage.value &&
oldModel.groupedWithPreviousMessage.value == newModel.groupedWithPreviousMessage.value
} else {
false
}

View file

@ -28,13 +28,13 @@ import org.linphone.utils.LinphoneUtils
class EventLogModel @WorkerThread constructor(
val eventLog: EventLog,
avatarModel: ContactAvatarModel,
isFromGroup: Boolean = false,
val avatarModel: ContactAvatarModel,
val isFromGroup: Boolean = false,
isGroupedWithPreviousOne: Boolean = false,
isGroupedWithNextOne: Boolean = false,
onContentClicked: ((file: String) -> Unit)? = null,
onJoinConferenceClicked: ((uri: String) -> Unit)? = null,
onWebUrlClicked: ((url: String) -> Unit)? = null
val onContentClicked: ((file: String) -> Unit)? = null,
val onJoinConferenceClicked: ((uri: String) -> Unit)? = null,
val onWebUrlClicked: ((url: String) -> Unit)? = null
) {
companion object {
private const val TAG = "[Event Log Model]"

View file

@ -66,8 +66,8 @@ class MessageModel @WorkerThread constructor(
val replyTo: String,
val replyText: String,
val replyToMessageId: String?,
val isGroupedWithPreviousOne: Boolean,
val isGroupedWithNextOne: Boolean,
isGroupedWithPreviousOne: Boolean,
isGroupedWithNextOne: Boolean,
private val onContentClicked: ((file: String) -> Unit)? = null,
private val onJoinConferenceClicked: ((uri: String) -> Unit)? = null,
private val onWebUrlClicked: ((url: String) -> Unit)? = null
@ -96,6 +96,10 @@ class MessageModel @WorkerThread constructor(
val chatRoomIsReadOnly = chatMessage.chatRoom.isReadOnly
val groupedWithNextMessage = MutableLiveData<Boolean>()
val groupedWithPreviousMessage = MutableLiveData<Boolean>()
val reactions = MutableLiveData<String>()
val filesList = MutableLiveData<ArrayList<FileModel>>()
@ -211,6 +215,8 @@ class MessageModel @WorkerThread constructor(
}
init {
groupedWithNextMessage.postValue(isGroupedWithNextOne)
groupedWithPreviousMessage.postValue(isGroupedWithPreviousOne)
isPlayingVoiceRecord.postValue(false)
chatMessage.addListener(chatMessageListener)

View file

@ -103,22 +103,27 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
val list = arrayListOf<EventLogModel>()
list.addAll(events.value.orEmpty())
val newList = getEventsListFromHistory(
arrayOf(eventLog),
searchFilter.value.orEmpty().trim()
)
val lastEvent = events.value.orEmpty().lastOrNull()
if (lastEvent != null && shouldWeGroupTwoEvents(eventLog, lastEvent.eventLog)) {
list.remove(lastEvent)
val eventsLogsArray = arrayOf(lastEvent.eventLog, eventLog)
val newList = getEventsListFromHistory(
eventsLogsArray,
searchFilter.value.orEmpty().trim()
val newEvent = newList.lastOrNull()
if (lastEvent != null && newEvent != null && shouldWeGroupTwoEvents(
newEvent.eventLog,
lastEvent.eventLog
)
list.addAll(newList)
} else {
val newList = getEventsListFromHistory(
arrayOf(eventLog),
searchFilter.value.orEmpty().trim()
)
list.addAll(newList)
) {
if (lastEvent.model is MessageModel) {
lastEvent.model.groupedWithNextMessage.postValue(true)
}
if (newEvent.model is MessageModel) {
newEvent.model.groupedWithPreviousMessage.postValue(true)
}
}
list.addAll(newList)
events.postValue(list)
}
@ -150,23 +155,25 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
list.addAll(events.value.orEmpty())
val lastEvent = list.lastOrNull()
if (lastEvent != null && shouldWeGroupTwoEvents(eventLogs.first(), lastEvent.eventLog)) {
list.remove(lastEvent)
val firstElement = arrayOf(lastEvent.eventLog)
val eventsLogsArray = firstElement.plus(eventLogs)
val newList = getEventsListFromHistory(
eventsLogsArray,
searchFilter.value.orEmpty().trim()
val newList = getEventsListFromHistory(
eventLogs,
searchFilter.value.orEmpty().trim()
)
val newEvent = newList.firstOrNull()
if (lastEvent != null && newEvent != null && shouldWeGroupTwoEvents(
newEvent.eventLog,
lastEvent.eventLog
)
list.addAll(newList)
} else {
val newList = getEventsListFromHistory(
eventLogs,
searchFilter.value.orEmpty().trim()
)
list.addAll(newList)
) {
if (lastEvent.model is MessageModel) {
lastEvent.model.groupedWithNextMessage.postValue(true)
}
if (newEvent.model is MessageModel) {
newEvent.model.groupedWithPreviousMessage.postValue(true)
}
}
list.addAll(newList)
events.postValue(list)
chatRoom.markAsRead()
}
@ -197,8 +204,13 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
if (found != null) {
val list = arrayListOf<EventLogModel>()
list.addAll(eventsLogs)
// Update previous & next messages if needed
updatePreviousAndNextMessages(list, found)
list.remove(found)
events.postValue(list)
Log.i("$TAG Message was removed from events list")
} else {
Log.w("$TAG Failed to find matching message in events list")
@ -320,6 +332,10 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
if (found != null) {
val list = arrayListOf<EventLogModel>()
list.addAll(eventsLogs)
// Update previous & next messages if needed
updatePreviousAndNextMessages(list, found)
list.remove(found)
events.postValue(list)
}
@ -489,6 +505,38 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
}
}
@WorkerThread
private fun updatePreviousAndNextMessages(list: ArrayList<EventLogModel>, found: EventLogModel) {
val index = list.indexOf(found)
if (found.model is MessageModel) {
val messageModel = found.model
if (messageModel.groupedWithNextMessage.value == true && messageModel.groupedWithPreviousMessage.value == true) {
Log.i(
"$TAG Deleted message was grouped with both next and previous one; nothing to do"
)
// Nothing to do
} else if (messageModel.groupedWithPreviousMessage.value == true) {
Log.i("$TAG Deleted message was grouped with previous one")
if (index > 0) {
val previous = list[index - 1]
if (previous.model is MessageModel) {
previous.model.groupedWithNextMessage.postValue(false)
Log.i("$TAG Previous message at [${index - 1}] was updated")
}
}
} else if (messageModel.groupedWithNextMessage.value == true) {
Log.i("$TAG Deleted message was grouped with next one")
if (index < list.size - 1) {
val next = list[index + 1]
if (next.model is MessageModel) {
next.model.groupedWithPreviousMessage.postValue(false)
Log.i("$TAG Next message at [${index + 1}] was updated")
}
}
}
}
}
@WorkerThread
private fun computeComposingLabel() {
val composingFriends = arrayListOf<String>()

View file

@ -31,14 +31,14 @@
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="32dp"
android:layout_marginTop="@{model.isGroupedWithPreviousOne ? @dimen/chat_bubble_grouped_top_margin : @dimen/chat_bubble_top_margin, default=@dimen/chat_bubble_top_margin}">
android:layout_marginTop="@{model.groupedWithPreviousMessage ? @dimen/chat_bubble_grouped_top_margin : @dimen/chat_bubble_top_margin, default=@dimen/chat_bubble_top_margin}">
<com.google.android.material.imageview.ShapeableImageView
style="@style/avatar_imageview"
android:id="@+id/avatar"
android:layout_width="@dimen/avatar_bubble_size"
android:layout_height="@dimen/avatar_bubble_size"
android:visibility="@{!model.isFromGroup ? View.GONE: model.isGroupedWithPreviousOne ? View.INVISIBLE : View.VISIBLE}"
android:visibility="@{!model.isFromGroup ? View.GONE: model.groupedWithPreviousMessage ? View.INVISIBLE : View.VISIBLE}"
coilBubbleAvatar="@{model.avatarModel}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/name" />
@ -50,7 +50,7 @@
android:layout_marginEnd="1dp"
android:background="@drawable/led_background"
android:padding="1dp"
android:visibility="@{model.isGroupedWithPreviousOne || !model.isFromGroup || model.avatarModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE}"
android:visibility="@{model.groupedWithPreviousMessage || !model.isFromGroup || model.avatarModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE}"
app:presenceIcon="@{model.avatarModel.presenceStatus}"
app:layout_constraintEnd_toEndOf="@id/avatar"
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
@ -65,7 +65,7 @@
android:textColor="@color/gray_main2_700"
android:maxLines="1"
android:ellipsize="end"
android:visibility="@{!model.isFromGroup ? View.GONE: model.isGroupedWithPreviousOne ? View.GONE : View.VISIBLE}"
android:visibility="@{!model.isFromGroup ? View.GONE: model.groupedWithPreviousMessage ? View.GONE : View.VISIBLE}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/reply_icon"
app:layout_constraintStart_toStartOf="@id/bubble" />
@ -139,7 +139,7 @@
android:padding="10dp"
android:orientation="vertical"
android:selected="@{model.isSelected}"
android:background="@{model.isGroupedWithPreviousOne ? @drawable/chat_bubble_incoming_full_background : @drawable/chat_bubble_incoming_first_background, default=@drawable/chat_bubble_incoming_first_background}"
android:background="@{model.groupedWithPreviousMessage ? @drawable/chat_bubble_incoming_full_background : @drawable/chat_bubble_incoming_first_background, default=@drawable/chat_bubble_incoming_first_background}"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintWidth_max="@dimen/chat_bubble_max_width"
app:layout_constraintTop_toBottomOf="@id/reply"
@ -214,7 +214,7 @@
android:layout_height="wrap_content"
android:text="@{model.time, default=`13:40`}"
android:textSize="12sp"
android:visibility="@{!model.isGroupedWithNextOne ? View.VISIBLE : View.GONE}"/>
android:visibility="@{!model.groupedWithNextMessage ? View.VISIBLE : View.GONE}"/>
<ImageView
style="@style/default_text_style_300"
@ -225,7 +225,7 @@
android:layout_marginStart="5dp"
android:layout_marginTop="2dp"
android:src="@{model.statusIcon, default=@drawable/checks}"
android:visibility="@{!model.isGroupedWithNextOne ? View.VISIBLE : View.GONE}"
android:visibility="@{!model.groupedWithNextMessage ? View.VISIBLE : View.GONE}"
app:tint="@color/orange_main_500" />
</LinearLayout>

View file

@ -31,7 +31,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="8dp"
android:layout_marginTop="@{model.isGroupedWithPreviousOne ? @dimen/chat_bubble_grouped_top_margin : @dimen/chat_bubble_top_margin, default=@dimen/chat_bubble_top_margin}">
android:layout_marginTop="@{model.groupedWithPreviousMessage ? @dimen/chat_bubble_grouped_top_margin : @dimen/chat_bubble_top_margin, default=@dimen/chat_bubble_top_margin}">
<androidx.constraintlayout.widget.Group
android:id="@+id/reply_group"
@ -101,7 +101,7 @@
android:orientation="vertical"
android:gravity="end"
android:selected="@{model.isSelected}"
android:background="@{model.isGroupedWithNextOne ? @drawable/chat_bubble_outgoing_full_background : @drawable/chat_bubble_outgoing_last_background, default=@drawable/chat_bubble_outgoing_last_background}"
android:background="@{model.groupedWithNextMessage ? @drawable/chat_bubble_outgoing_full_background : @drawable/chat_bubble_outgoing_last_background, default=@drawable/chat_bubble_outgoing_last_background}"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintWidth_max="@dimen/chat_bubble_max_width"
app:layout_constraintTop_toBottomOf="@id/reply"
@ -176,7 +176,7 @@
android:layout_height="wrap_content"
android:text="@{model.time, default=`13:40`}"
android:textSize="12sp"
android:visibility="@{!model.isGroupedWithNextOne ? View.VISIBLE : View.GONE}"/>
android:visibility="@{!model.groupedWithNextMessage ? View.VISIBLE : View.GONE}"/>
<ImageView
style="@style/default_text_style_300"
@ -187,7 +187,7 @@
android:layout_marginStart="5dp"
android:layout_marginTop="2dp"
android:src="@{model.statusIcon, default=@drawable/checks}"
android:visibility="@{!model.isGroupedWithNextOne ? View.VISIBLE : View.GONE}"
android:visibility="@{!model.groupedWithNextMessage ? View.VISIBLE : View.GONE}"
app:tint="@color/orange_main_500" />
</LinearLayout>