diff --git a/library/ui-strings/src/main/res/values/strings_sc.xml b/library/ui-strings/src/main/res/values/strings_sc.xml index 6e1363fc94..329b808b0a 100644 --- a/library/ui-strings/src/main/res/values/strings_sc.xml +++ b/library/ui-strings/src/main/res/values/strings_sc.xml @@ -162,6 +162,7 @@ <string name="settings_sc_dbg_timeline_chunks">Timeline consistency debugging</string> <string name="settings_sc_dbg_show_display_index">Show displayIndex in timeline</string> <string name="settings_sc_dbg_show_read_tracking">Show read tracking</string> + <string name="settings_sc_dbg_read_receipts">Read receipt debugging</string> <string name="settings_sc_dbg_view_pager">ViewPager debugging</string> <string name="settings_sc_dbg_view_pager_visuals">Show ViewPager debugging information</string> diff --git a/matrix-sdk-android/src/main/java/de/spiritcroc/matrixsdk/util/DbgUtil.kt b/matrix-sdk-android/src/main/java/de/spiritcroc/matrixsdk/util/DbgUtil.kt index 5b768a12ab..6825be65ac 100644 --- a/matrix-sdk-android/src/main/java/de/spiritcroc/matrixsdk/util/DbgUtil.kt +++ b/matrix-sdk-android/src/main/java/de/spiritcroc/matrixsdk/util/DbgUtil.kt @@ -8,6 +8,7 @@ import timber.log.Timber object DbgUtil { const val DBG_READ_MARKER = "DBG_READ_MARKER" const val DBG_SHOW_READ_TRACKING = "DBG_SHOW_READ_TRACKING" + const val DBG_READ_RECEIPTS = "DBG_READ_RECEIPTS" const val DBG_TIMELINE_CHUNKS = "DBG_TIMELINE_CHUNKS" const val DBG_SHOW_DISPLAY_INDEX = "DBG_SHOW_DISPLAY_INDEX" const val DBG_VIEW_PAGER = "DBG_VIEW_PAGER" @@ -18,6 +19,7 @@ object DbgUtil { val ALL_PREFS = arrayOf( DBG_READ_MARKER, DBG_SHOW_READ_TRACKING, + DBG_READ_RECEIPTS, DBG_TIMELINE_CHUNKS, DBG_SHOW_DISPLAY_INDEX, DBG_VIEW_PAGER, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ChunkEntityHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ChunkEntityHelper.kt index bc20bc0a32..55ec1de925 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ChunkEntityHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ChunkEntityHelper.kt @@ -16,6 +16,7 @@ package org.matrix.android.sdk.internal.database.helper +import de.spiritcroc.matrixsdk.util.DbgUtil import de.spiritcroc.matrixsdk.util.Dimber import io.realm.Realm import io.realm.kotlin.createObject @@ -125,6 +126,8 @@ internal fun computeIsUnique( } } +val rrDimber = Dimber("ReadReceipts", DbgUtil.DBG_READ_RECEIPTS) + private fun handleReadReceipts(realm: Realm, roomId: String, eventEntity: EventEntity, senderId: String): ReadReceiptsSummaryEntity { val readReceiptsSummaryEntity = ReadReceiptsSummaryEntity.where(realm, eventEntity.eventId).findFirst() ?: realm.createObject<ReadReceiptsSummaryEntity>(eventEntity.eventId).apply { @@ -137,10 +140,13 @@ private fun handleReadReceipts(realm: Realm, roomId: String, eventEntity: EventE // If the synced RR is older, update if (timestampOfEvent > readReceiptOfSender.originServerTs) { val previousReceiptsSummary = ReadReceiptsSummaryEntity.where(realm, eventId = readReceiptOfSender.eventId).findFirst() + rrDimber.i{"Handle outdated chunk RR $roomId / $senderId thread ${eventEntity.rootThreadEventId}: event ${readReceiptOfSender.eventId} -> ${eventEntity.eventId}"} readReceiptOfSender.eventId = eventEntity.eventId readReceiptOfSender.originServerTs = timestampOfEvent previousReceiptsSummary?.readReceipts?.remove(readReceiptOfSender) readReceiptsSummaryEntity.readReceipts.add(readReceiptOfSender) + } else { + rrDimber.i{"Handled chunk RR $roomId / $senderId thread ${eventEntity.rootThreadEventId}: keep ${readReceiptOfSender.eventId} (not ${eventEntity.eventId})"} } } return readReceiptsSummaryEntity diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/ReadReceiptsSummaryMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/ReadReceiptsSummaryMapper.kt index 3b71ae3dea..4375b5c83a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/ReadReceiptsSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/ReadReceiptsSummaryMapper.kt @@ -16,6 +16,8 @@ package org.matrix.android.sdk.internal.database.mapper +import de.spiritcroc.matrixsdk.util.DbgUtil +import de.spiritcroc.matrixsdk.util.Dimber import io.realm.Realm import io.realm.RealmList import org.matrix.android.sdk.api.session.room.model.ReadReceipt @@ -30,6 +32,8 @@ internal class ReadReceiptsSummaryMapper @Inject constructor( private val realmSessionProvider: RealmSessionProvider ) { + val rrDimber = Dimber("ReadReceipts", DbgUtil.DBG_READ_RECEIPTS) + fun map(readReceiptsSummaryEntity: ReadReceiptsSummaryEntity?): List<ReadReceipt> { if (readReceiptsSummaryEntity == null) { return emptyList() @@ -48,6 +52,7 @@ internal class ReadReceiptsSummaryMapper @Inject constructor( private fun map(readReceipts: RealmList<ReadReceiptEntity>, realm: Realm): List<ReadReceipt> { return readReceipts .mapNotNull { + rrDimber.i{"Map ${it.eventId} receipt ${it.userId} thread ${it.threadId}"} val roomMember = RoomMemberSummaryEntity.where(realm, roomId = it.roomId, userId = it.userId).findFirst() ?: return@mapNotNull null ReadReceipt(roomMember.asDomain(), it.originServerTs.toLong(), it.threadId) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ReadReceiptHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ReadReceiptHandler.kt index 7f12ce653c..40dce190c5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ReadReceiptHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ReadReceiptHandler.kt @@ -16,6 +16,8 @@ package org.matrix.android.sdk.internal.session.sync.handler.room +import de.spiritcroc.matrixsdk.util.DbgUtil +import de.spiritcroc.matrixsdk.util.Dimber import io.realm.Realm import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.internal.database.model.ReadReceiptEntity @@ -43,6 +45,8 @@ internal class ReadReceiptHandler @Inject constructor( private val roomSyncEphemeralTemporaryStore: RoomSyncEphemeralTemporaryStore ) { + val rrDimber = Dimber("ReadReceipts", DbgUtil.DBG_READ_RECEIPTS) + companion object { fun createContent( @@ -107,6 +111,7 @@ internal class ReadReceiptHandler @Inject constructor( val ts = paramsDict[TIMESTAMP_KEY] as? Double ?: 0.0 val threadId = paramsDict[THREAD_ID_KEY] as String? val receiptEntity = ReadReceiptEntity.createUnmanaged(roomId, eventId, userId, threadId, ts) + rrDimber.i{"Handle initial sync RR $roomId / $userId thread $threadId: event $eventId"} readReceiptsSummary.readReceipts.add(receiptEntity) } readReceiptSummaries.add(readReceiptsSummary) @@ -144,12 +149,15 @@ internal class ReadReceiptHandler @Inject constructor( val receiptEntity = ReadReceiptEntity.getOrCreate(realm, roomId, userId, threadId) // ensure new ts is superior to the previous one if (ts > receiptEntity.originServerTs) { + rrDimber.i{"Handle outdated sync RR $roomId / $userId thread $threadId: event ${receiptEntity.eventId} -> $eventId"} ReadReceiptsSummaryEntity.where(realm, receiptEntity.eventId).findFirst()?.also { it.readReceipts.remove(receiptEntity) } receiptEntity.eventId = eventId receiptEntity.originServerTs = ts readReceiptsSummary.readReceipts.add(receiptEntity) + } else { + rrDimber.i{"Handle keep sync RR $roomId / $userId thread $threadId: event ${receiptEntity.eventId} (not $eventId)"} } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt index a489c1ec66..eef2d8e69c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt @@ -26,6 +26,7 @@ import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.core.epoxy.onClick +import im.vector.app.core.extensions.setTextOrHide import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer import org.matrix.android.sdk.api.util.MatrixItem @@ -37,11 +38,13 @@ abstract class DisplayReadReceiptItem : VectorEpoxyModel<DisplayReadReceiptItem. @EpoxyAttribute var timestamp: String? = null @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var userClicked: ClickListener? = null + @EpoxyAttribute var debugInfo: String? = null override fun bind(holder: Holder) { super.bind(holder) avatarRenderer.render(matrixItem, holder.avatarView) holder.displayNameView.text = matrixItem.getBestName() + holder.debugView.setTextOrHide(debugInfo) timestamp?.let { holder.timestampView.text = it holder.timestampView.isVisible = true @@ -54,6 +57,7 @@ abstract class DisplayReadReceiptItem : VectorEpoxyModel<DisplayReadReceiptItem. class Holder : VectorEpoxyHolder() { val avatarView by bind<ImageView>(R.id.readReceiptAvatar) val displayNameView by bind<TextView>(R.id.readReceiptName) + val debugView by bind<TextView>(R.id.readReceiptDebugAdd) val timestampView by bind<TextView>(R.id.readReceiptDate) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptsController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptsController.kt index 76f2d72456..5bbf5477c0 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptsController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/readreceipts/DisplayReadReceiptsController.kt @@ -17,6 +17,7 @@ package im.vector.app.features.home.room.detail.readreceipts import com.airbnb.epoxy.TypedEpoxyController +import de.spiritcroc.matrixsdk.util.DbgUtil import im.vector.app.core.date.DateFormatKind import im.vector.app.core.date.VectorDateFormatter import im.vector.app.features.home.AvatarRenderer @@ -43,6 +44,7 @@ class DisplayReadReceiptsController @Inject constructor( DisplayReadReceiptItem_() .id(readReceiptData.userId) .matrixItem(readReceiptData.toMatrixItem()) + .debugInfo(readReceiptData.threadId.toString().takeIf { DbgUtil.isDbgEnabled(DbgUtil.DBG_READ_RECEIPTS) }) .avatarRenderer(avatarRender) .timestamp(timestamp) .userClicked { listener?.didSelectUser(readReceiptData.userId) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/ReadReceiptsItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/ReadReceiptsItemFactory.kt index 15b6e73759..f9b1e98063 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/ReadReceiptsItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/ReadReceiptsItemFactory.kt @@ -45,7 +45,7 @@ class ReadReceiptsItemFactory @Inject constructor( } val readReceiptsData = readReceipts .map { - ReadReceiptData(it.roomMember.userId, it.roomMember.avatarUrl, it.roomMember.displayName, it.originServerTs) + ReadReceiptData(it.roomMember.userId, it.roomMember.avatarUrl, it.roomMember.displayName, it.originServerTs, it.threadId) } .sortedByDescending { it.timestamp } val threadReadReceiptsSupported = session.homeServerCapabilitiesService().getHomeServerCapabilities().canUseThreadReadReceiptsAndNotifications diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageInformationData.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageInformationData.kt index 5e2ecbae78..3a88a982e4 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageInformationData.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageInformationData.kt @@ -88,7 +88,8 @@ data class ReadReceiptData( val userId: String, val avatarUrl: String?, val displayName: String?, - val timestamp: Long + val timestamp: Long, + val threadId: String?, ) : Parcelable @Parcelize diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsScDebuggingFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsScDebuggingFragment.kt index 1a918df26c..0a0f863b52 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsScDebuggingFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsScDebuggingFragment.kt @@ -20,6 +20,7 @@ class VectorSettingsScDebuggingFragment @Inject constructor( DbgPref(DbgUtil.DBG_SHOW_DISPLAY_INDEX, R.string.settings_sc_dbg_show_display_index), DbgPref(DbgUtil.DBG_READ_MARKER, R.string.settings_sc_dbg_read_marker), DbgPref(DbgUtil.DBG_SHOW_READ_TRACKING, R.string.settings_sc_dbg_show_read_tracking), + DbgPref(DbgUtil.DBG_READ_RECEIPTS, R.string.settings_sc_dbg_read_receipts), DbgPref(DbgUtil.DBG_VIEW_PAGER, R.string.settings_sc_dbg_view_pager), DbgPref(DbgUtil.DBG_VIEW_PAGER_VISUALS, R.string.settings_sc_dbg_view_pager_visuals), ) diff --git a/vector/src/main/res/layout/item_display_read_receipt.xml b/vector/src/main/res/layout/item_display_read_receipt.xml index 90c605c9c8..747b5ca2ad 100644 --- a/vector/src/main/res/layout/item_display_read_receipt.xml +++ b/vector/src/main/res/layout/item_display_read_receipt.xml @@ -24,6 +24,14 @@ style="@style/BottomSheetItemTextMain" tools:text="@sample/users.json/data/displayName" /> + <TextView + android:id="@+id/readReceiptDebugAdd" + style="@style/BottomSheetItemTextSecondary" + android:maxLines="1" + android:ellipsize="end" + android:layout_marginHorizontal="8dp" + tools:text="@sample/messages.json/data/message" /> + <TextView android:id="@+id/readReceiptDate" style="@style/BottomSheetItemTime"