mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 13:38:49 +03:00
Read receipts: use a simpler strategy when it's initialSync
This commit is contained in:
parent
b4ce8748cb
commit
d98567045c
3 changed files with 54 additions and 16 deletions
|
@ -31,27 +31,62 @@ import javax.inject.Inject
|
||||||
// dict value ts value
|
// dict value ts value
|
||||||
typealias ReadReceiptContent = Map<String, Map<String, Map<String, Map<String, Double>>>>
|
typealias ReadReceiptContent = Map<String, Map<String, Map<String, Map<String, Double>>>>
|
||||||
|
|
||||||
|
private const val READ_KEY = "m.read"
|
||||||
|
private const val TIMESTAMP_KEY = "ts"
|
||||||
|
|
||||||
internal class ReadReceiptHandler @Inject constructor() {
|
internal class ReadReceiptHandler @Inject constructor() {
|
||||||
|
|
||||||
fun handle(realm: Realm, roomId: String, content: ReadReceiptContent?) {
|
fun handle(realm: Realm, roomId: String, content: ReadReceiptContent?, isInitialSync: Boolean) {
|
||||||
if (content == null) {
|
if (content == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
handleReadReceiptContent(realm, roomId, content)
|
handleReadReceiptContent(realm, roomId, content, isInitialSync)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
Timber.e("Fail to handle read receipt for room $roomId")
|
Timber.e("Fail to handle read receipt for room $roomId")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleReadReceiptContent(realm: Realm, roomId: String, content: ReadReceiptContent) {
|
private fun handleReadReceiptContent(realm: Realm, roomId: String, content: ReadReceiptContent, isInitialSync: Boolean) {
|
||||||
|
if (isInitialSync) {
|
||||||
|
initialSyncStrategy(realm, roomId, content)
|
||||||
|
} else {
|
||||||
|
incrementalSyncStrategy(realm, roomId, content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun initialSyncStrategy(realm: Realm, roomId: String, content: ReadReceiptContent) {
|
||||||
|
val readReceiptSummaries = ArrayList<ReadReceiptsSummaryEntity>()
|
||||||
for ((eventId, receiptDict) in content) {
|
for ((eventId, receiptDict) in content) {
|
||||||
val userIdsDict = receiptDict["m.read"] ?: continue
|
val userIdsDict = receiptDict[READ_KEY] ?: continue
|
||||||
|
val readReceiptsSummary = ReadReceiptsSummaryEntity(eventId = eventId)
|
||||||
|
|
||||||
|
for ((userId, paramsDict) in userIdsDict) {
|
||||||
|
val ts = paramsDict[TIMESTAMP_KEY] ?: 0.0
|
||||||
|
val primaryKey = "${roomId}_$userId"
|
||||||
|
val receiptEntity = ReadReceiptEntity().apply {
|
||||||
|
this.primaryKey = primaryKey
|
||||||
|
this.eventId = eventId
|
||||||
|
this.roomId = roomId
|
||||||
|
this.userId = userId
|
||||||
|
this.originServerTs = ts
|
||||||
|
}
|
||||||
|
readReceiptsSummary.readReceipts.add(receiptEntity)
|
||||||
|
}
|
||||||
|
readReceiptSummaries.add(readReceiptsSummary)
|
||||||
|
}
|
||||||
|
realm.insertOrUpdate(readReceiptSummaries)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun incrementalSyncStrategy(realm: Realm, roomId: String, content: ReadReceiptContent) {
|
||||||
|
for ((eventId, receiptDict) in content) {
|
||||||
|
val userIdsDict = receiptDict[READ_KEY] ?: continue
|
||||||
val readReceiptsSummary = ReadReceiptsSummaryEntity.where(realm, eventId).findFirst()
|
val readReceiptsSummary = ReadReceiptsSummaryEntity.where(realm, eventId).findFirst()
|
||||||
?: realm.createObject(ReadReceiptsSummaryEntity::class.java, eventId)
|
?: realm.createObject(ReadReceiptsSummaryEntity::class.java, eventId)
|
||||||
|
|
||||||
for ((userId, paramsDict) in userIdsDict) {
|
for ((userId, paramsDict) in userIdsDict) {
|
||||||
val ts = paramsDict["ts"] ?: 0.0
|
val ts = paramsDict[TIMESTAMP_KEY] ?: 0.0
|
||||||
val primaryKey = "${roomId}_$userId"
|
val primaryKey = "${roomId}_$userId"
|
||||||
val receiptEntity = ReadReceiptEntity.where(realm, roomId, userId).findFirst()
|
val receiptEntity = ReadReceiptEntity.where(realm, roomId, userId).findFirst()
|
||||||
?: realm.createObject(ReadReceiptEntity::class.java, primaryKey)
|
?: realm.createObject(ReadReceiptEntity::class.java, primaryKey)
|
||||||
|
@ -69,4 +104,5 @@ internal class ReadReceiptHandler @Inject constructor() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -62,11 +62,11 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
||||||
data class LEFT(val data: Map<String, RoomSync>) : HandlingStrategy()
|
data class LEFT(val data: Map<String, RoomSync>) : HandlingStrategy()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handle(roomsSyncResponse: RoomsSyncResponse, reporter: DefaultInitialSyncProgressService? = null) {
|
fun handle(roomsSyncResponse: RoomsSyncResponse, isInitialSync: Boolean, reporter: DefaultInitialSyncProgressService? = null) {
|
||||||
monarchy.runTransactionSync { realm ->
|
monarchy.runTransactionSync { realm ->
|
||||||
handleRoomSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join), reporter)
|
handleRoomSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join), isInitialSync, reporter)
|
||||||
handleRoomSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite), reporter)
|
handleRoomSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite), isInitialSync, reporter)
|
||||||
handleRoomSync(realm, HandlingStrategy.LEFT(roomsSyncResponse.leave), reporter)
|
handleRoomSync(realm, HandlingStrategy.LEFT(roomsSyncResponse.leave), isInitialSync, reporter)
|
||||||
}
|
}
|
||||||
|
|
||||||
//handle event for bing rule checks
|
//handle event for bing rule checks
|
||||||
|
@ -89,12 +89,12 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
||||||
|
|
||||||
// PRIVATE METHODS *****************************************************************************
|
// PRIVATE METHODS *****************************************************************************
|
||||||
|
|
||||||
private fun handleRoomSync(realm: Realm, handlingStrategy: HandlingStrategy, reporter: DefaultInitialSyncProgressService?) {
|
private fun handleRoomSync(realm: Realm, handlingStrategy: HandlingStrategy, isInitialSync: Boolean, reporter: DefaultInitialSyncProgressService?) {
|
||||||
|
|
||||||
val rooms = when (handlingStrategy) {
|
val rooms = when (handlingStrategy) {
|
||||||
is HandlingStrategy.JOINED ->
|
is HandlingStrategy.JOINED ->
|
||||||
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_joined_rooms, 0.6f) {
|
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_joined_rooms, 0.6f) {
|
||||||
handleJoinedRoom(realm, it.key, it.value)
|
handleJoinedRoom(realm, it.key, it.value, isInitialSync)
|
||||||
}
|
}
|
||||||
is HandlingStrategy.INVITED ->
|
is HandlingStrategy.INVITED ->
|
||||||
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_invited_rooms, 0.4f) {
|
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_invited_rooms, 0.4f) {
|
||||||
|
@ -112,7 +112,8 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
||||||
|
|
||||||
private fun handleJoinedRoom(realm: Realm,
|
private fun handleJoinedRoom(realm: Realm,
|
||||||
roomId: String,
|
roomId: String,
|
||||||
roomSync: RoomSync): RoomEntity {
|
roomSync: RoomSync,
|
||||||
|
isInitalSync: Boolean): RoomEntity {
|
||||||
|
|
||||||
Timber.v("Handle join sync for room $roomId")
|
Timber.v("Handle join sync for room $roomId")
|
||||||
|
|
||||||
|
@ -152,7 +153,7 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
||||||
roomSummaryUpdater.update(realm, roomId, Membership.JOIN, roomSync.summary, roomSync.unreadNotifications)
|
roomSummaryUpdater.update(realm, roomId, Membership.JOIN, roomSync.summary, roomSync.unreadNotifications)
|
||||||
|
|
||||||
if (roomSync.ephemeral != null && roomSync.ephemeral.events.isNotEmpty()) {
|
if (roomSync.ephemeral != null && roomSync.ephemeral.events.isNotEmpty()) {
|
||||||
handleEphemeral(realm, roomId, roomSync.ephemeral)
|
handleEphemeral(realm, roomId, roomSync.ephemeral, isInitalSync)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (roomSync.accountData != null && roomSync.accountData.events.isNullOrEmpty().not()) {
|
if (roomSync.accountData != null && roomSync.accountData.events.isNullOrEmpty().not()) {
|
||||||
|
@ -236,11 +237,12 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
private fun handleEphemeral(realm: Realm,
|
private fun handleEphemeral(realm: Realm,
|
||||||
roomId: String,
|
roomId: String,
|
||||||
ephemeral: RoomSyncEphemeral) {
|
ephemeral: RoomSyncEphemeral,
|
||||||
|
isInitalSync: Boolean) {
|
||||||
for (event in ephemeral.events) {
|
for (event in ephemeral.events) {
|
||||||
if (event.type != EventType.RECEIPT) continue
|
if (event.type != EventType.RECEIPT) continue
|
||||||
val readReceiptContent = event.content as? ReadReceiptContent ?: continue
|
val readReceiptContent = event.content as? ReadReceiptContent ?: continue
|
||||||
readReceiptHandler.handle(realm, roomId, readReceiptContent)
|
readReceiptHandler.handle(realm, roomId, readReceiptContent, isInitalSync)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ internal class SyncResponseHandler @Inject constructor(private val roomSyncHandl
|
||||||
|
|
||||||
reportSubtask(reporter, R.string.initial_sync_start_importing_account_rooms, 100, 0.7f) {
|
reportSubtask(reporter, R.string.initial_sync_start_importing_account_rooms, 100, 0.7f) {
|
||||||
if (syncResponse.rooms != null) {
|
if (syncResponse.rooms != null) {
|
||||||
roomSyncHandler.handle(syncResponse.rooms, reporter)
|
roomSyncHandler.handle(syncResponse.rooms, isInitialSync, reporter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.also {
|
}.also {
|
||||||
|
|
Loading…
Reference in a new issue