mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-15 01:35:07 +08:00
Merge pull request #334 from vector-im/feature/general_perf
Feature/general perf
This commit is contained in:
commit
252b2ea30a
@ -19,4 +19,4 @@ package im.vector.matrix.android
|
|||||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
|
|
||||||
internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main, Main)
|
internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main, Main, Main)
|
@ -30,7 +30,7 @@ import im.vector.matrix.android.api.session.room.send.SendState
|
|||||||
*/
|
*/
|
||||||
data class TimelineEvent(
|
data class TimelineEvent(
|
||||||
val root: Event,
|
val root: Event,
|
||||||
val localId: String,
|
val localId: Long,
|
||||||
val displayIndex: Int,
|
val displayIndex: Int,
|
||||||
val senderName: String?,
|
val senderName: String?,
|
||||||
val isUniqueDisplayName: Boolean,
|
val isUniqueDisplayName: Boolean,
|
||||||
|
@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.database
|
|||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.internal.util.createBackgroundHandler
|
import im.vector.matrix.android.internal.util.createBackgroundHandler
|
||||||
import io.realm.OrderedCollectionChangeSet
|
import io.realm.OrderedCollectionChangeSet
|
||||||
|
import io.realm.OrderedRealmCollectionChangeListener
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
@ -33,7 +34,7 @@ internal interface LiveEntityObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val realmConfiguration: RealmConfiguration)
|
internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val realmConfiguration: RealmConfiguration)
|
||||||
: LiveEntityObserver {
|
: LiveEntityObserver, OrderedRealmCollectionChangeListener<RealmResults<T>> {
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
val BACKGROUND_HANDLER = createBackgroundHandler("LIVE_ENTITY_BACKGROUND")
|
val BACKGROUND_HANDLER = createBackgroundHandler("LIVE_ENTITY_BACKGROUND")
|
||||||
@ -50,9 +51,7 @@ internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val r
|
|||||||
val realm = Realm.getInstance(realmConfiguration)
|
val realm = Realm.getInstance(realmConfiguration)
|
||||||
backgroundRealm.set(realm)
|
backgroundRealm.set(realm)
|
||||||
val queryResults = query.createQuery(realm).findAll()
|
val queryResults = query.createQuery(realm).findAll()
|
||||||
queryResults.addChangeListener { t, changeSet ->
|
queryResults.addChangeListener(this)
|
||||||
onChanged(t, changeSet)
|
|
||||||
}
|
|
||||||
results = AtomicReference(queryResults)
|
results = AtomicReference(queryResults)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,19 +72,4 @@ internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val r
|
|||||||
return isStarted.get()
|
return isStarted.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onChanged(realmResults: RealmResults<T>, changeSet: OrderedCollectionChangeSet) {
|
|
||||||
val insertionIndexes = changeSet.insertions
|
|
||||||
val updateIndexes = changeSet.changes
|
|
||||||
val deletionIndexes = changeSet.deletions
|
|
||||||
val inserted = realmResults.filterIndexed { index, _ -> insertionIndexes.contains(index) }
|
|
||||||
val updated = realmResults.filterIndexed { index, _ -> updateIndexes.contains(index) }
|
|
||||||
val deleted = realmResults.filterIndexed { index, _ -> deletionIndexes.contains(index) }
|
|
||||||
processChanges(inserted, updated, deleted)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do quick treatment or delegate on a task
|
|
||||||
*/
|
|
||||||
protected abstract fun processChanges(inserted: List<T>, updated: List<T>, deleted: List<T>)
|
|
||||||
|
|
||||||
}
|
}
|
@ -134,7 +134,8 @@ internal fun ChunkEntity.add(roomId: String,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val eventEntity = TimelineEventEntity().also {
|
val localId = TimelineEventEntity.nextId(realm)
|
||||||
|
val eventEntity = TimelineEventEntity(localId).also {
|
||||||
it.root = event.toEntity(roomId).apply {
|
it.root = event.toEntity(roomId).apply {
|
||||||
this.stateIndex = currentStateIndex
|
this.stateIndex = currentStateIndex
|
||||||
this.isUnlinked = isUnlinked
|
this.isUnlinked = isUnlinked
|
||||||
|
@ -26,7 +26,6 @@ import im.vector.matrix.android.internal.database.query.fastContains
|
|||||||
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||||
|
|
||||||
|
|
||||||
internal fun RoomEntity.deleteOnCascade(chunkEntity: ChunkEntity) {
|
internal fun RoomEntity.deleteOnCascade(chunkEntity: ChunkEntity) {
|
||||||
chunks.remove(chunkEntity)
|
chunks.remove(chunkEntity)
|
||||||
chunkEntity.deleteOnCascade()
|
chunkEntity.deleteOnCascade()
|
||||||
@ -65,7 +64,8 @@ internal fun RoomEntity.addSendingEvent(event: Event) {
|
|||||||
}
|
}
|
||||||
val roomMembers = RoomMembers(realm, roomId)
|
val roomMembers = RoomMembers(realm, roomId)
|
||||||
val myUser = roomMembers.get(senderId)
|
val myUser = roomMembers.get(senderId)
|
||||||
val timelineEventEntity = TimelineEventEntity().also {
|
val localId = TimelineEventEntity.nextId(realm)
|
||||||
|
val timelineEventEntity = TimelineEventEntity(localId).also {
|
||||||
it.root = eventEntity
|
it.root = eventEntity
|
||||||
it.eventId = event.eventId ?: ""
|
it.eventId = event.eventId ?: ""
|
||||||
it.roomId = roomId
|
it.roomId = roomId
|
||||||
|
@ -30,9 +30,11 @@ import im.vector.matrix.android.internal.database.query.prev
|
|||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||||
|
import io.realm.Realm
|
||||||
import io.realm.RealmList
|
import io.realm.RealmList
|
||||||
import io.realm.RealmQuery
|
import io.realm.RealmQuery
|
||||||
|
|
||||||
|
|
||||||
internal fun TimelineEventEntity.updateSenderData() {
|
internal fun TimelineEventEntity.updateSenderData() {
|
||||||
assertIsManaged()
|
assertIsManaged()
|
||||||
val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst() ?: return
|
val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst() ?: return
|
||||||
@ -69,6 +71,15 @@ internal fun TimelineEventEntity.updateSenderData() {
|
|||||||
this.senderMembershipEvent = senderMembershipEvent
|
this.senderMembershipEvent = senderMembershipEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun TimelineEventEntity.Companion.nextId(realm: Realm): Long{
|
||||||
|
val currentIdNum = realm.where(TimelineEventEntity::class.java).max(TimelineEventEntityFields.LOCAL_ID)
|
||||||
|
return if (currentIdNum == null) {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
currentIdNum.toLong() + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun RealmList<TimelineEventEntity>.buildQuery(sender: String, isUnlinked: Boolean): RealmQuery<TimelineEventEntity> {
|
private fun RealmList<TimelineEventEntity>.buildQuery(sender: String, isUnlinked: Boolean): RealmQuery<TimelineEventEntity> {
|
||||||
return where()
|
return where()
|
||||||
.equalTo(TimelineEventEntityFields.ROOT.STATE_KEY, sender)
|
.equalTo(TimelineEventEntityFields.ROOT.STATE_KEY, sender)
|
||||||
|
@ -35,7 +35,7 @@ internal object EventMapper {
|
|||||||
val uds = if (event.unsignedData == null) null
|
val uds = if (event.unsignedData == null) null
|
||||||
else MoshiProvider.providesMoshi().adapter(UnsignedData::class.java).toJson(event.unsignedData)
|
else MoshiProvider.providesMoshi().adapter(UnsignedData::class.java).toJson(event.unsignedData)
|
||||||
val eventEntity = EventEntity()
|
val eventEntity = EventEntity()
|
||||||
eventEntity.eventId = event.eventId ?: UUID.randomUUID().toString()
|
eventEntity.eventId = event.eventId ?: ""
|
||||||
eventEntity.roomId = event.roomId ?: roomId
|
eventEntity.roomId = event.roomId ?: roomId
|
||||||
eventEntity.content = ContentMapper.map(event.content)
|
eventEntity.content = ContentMapper.map(event.content)
|
||||||
val resolvedPrevContent = event.prevContent ?: event.unsignedData?.prevContent
|
val resolvedPrevContent = event.prevContent ?: event.unsignedData?.prevContent
|
||||||
|
@ -23,15 +23,6 @@ import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
|||||||
|
|
||||||
internal object TimelineEventMapper {
|
internal object TimelineEventMapper {
|
||||||
|
|
||||||
fun map(timelineEvent: TimelineEvent, roomId: String): TimelineEventEntity {
|
|
||||||
val timelineEventEntity = TimelineEventEntity()
|
|
||||||
timelineEventEntity.root = timelineEvent.root.toEntity(roomId)
|
|
||||||
timelineEventEntity.eventId = timelineEvent.root.eventId ?: ""
|
|
||||||
timelineEventEntity.roomId = roomId
|
|
||||||
timelineEventEntity.annotations = timelineEvent.annotations?.let { EventAnnotationsSummaryMapper.map(it, roomId) }
|
|
||||||
return timelineEventEntity
|
|
||||||
}
|
|
||||||
|
|
||||||
fun map(timelineEventEntity: TimelineEventEntity): TimelineEvent {
|
fun map(timelineEventEntity: TimelineEventEntity): TimelineEvent {
|
||||||
|
|
||||||
return TimelineEvent(
|
return TimelineEvent(
|
||||||
@ -53,8 +44,4 @@ internal fun TimelineEventEntity.asDomain(): TimelineEvent {
|
|||||||
return TimelineEventMapper.map(this)
|
return TimelineEventMapper.map(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun TimelineEvent.toEntity(roomId: String): TimelineEventEntity {
|
|
||||||
return TimelineEventMapper.map(this, roomId)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,8 +27,7 @@ import io.realm.annotations.LinkingObjects
|
|||||||
import io.realm.annotations.PrimaryKey
|
import io.realm.annotations.PrimaryKey
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
internal open class EventEntity(@PrimaryKey var localId: String = UUID.randomUUID().toString(),
|
internal open class EventEntity(@Index var eventId: String = "",
|
||||||
@Index var eventId: String = "",
|
|
||||||
@Index var roomId: String = "",
|
@Index var roomId: String = "",
|
||||||
@Index var type: String = "",
|
@Index var type: String = "",
|
||||||
var content: String? = null,
|
var content: String? = null,
|
||||||
|
@ -16,10 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.internal.database.model
|
package im.vector.matrix.android.internal.database.model
|
||||||
|
|
||||||
import com.squareup.moshi.Types
|
|
||||||
import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
|
|
||||||
import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
|
||||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmResults
|
||||||
import io.realm.annotations.Index
|
import io.realm.annotations.Index
|
||||||
@ -28,7 +24,7 @@ import io.realm.annotations.PrimaryKey
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
internal open class TimelineEventEntity(@PrimaryKey var localId: String = UUID.randomUUID().toString(),
|
internal open class TimelineEventEntity(var localId: Long = 0,
|
||||||
@Index var eventId: String = "",
|
@Index var eventId: String = "",
|
||||||
@Index var roomId: String = "",
|
@Index var roomId: String = "",
|
||||||
var root: EventEntity? = null,
|
var root: EventEntity? = null,
|
||||||
|
@ -18,15 +18,15 @@ package im.vector.matrix.android.internal.di
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.os.Handler
|
|
||||||
import android.os.HandlerThread
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
import im.vector.matrix.android.internal.util.createBackgroundHandler
|
import im.vector.matrix.android.internal.util.createBackgroundHandler
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.android.asCoroutineDispatcher
|
import kotlinx.coroutines.android.asCoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.asCoroutineDispatcher
|
||||||
import org.matrix.olm.OlmManager
|
import org.matrix.olm.OlmManager
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
internal object MatrixModule {
|
internal object MatrixModule {
|
||||||
@ -38,7 +38,8 @@ internal object MatrixModule {
|
|||||||
return MatrixCoroutineDispatchers(io = Dispatchers.IO,
|
return MatrixCoroutineDispatchers(io = Dispatchers.IO,
|
||||||
computation = Dispatchers.IO,
|
computation = Dispatchers.IO,
|
||||||
main = Dispatchers.Main,
|
main = Dispatchers.Main,
|
||||||
crypto = createBackgroundHandler("Crypto_Thread").asCoroutineDispatcher()
|
crypto = createBackgroundHandler("Crypto_Thread").asCoroutineDispatcher(),
|
||||||
|
sync = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import android.content.Context
|
|||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import androidx.annotation.MainThread
|
import androidx.annotation.MainThread
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
|
import dagger.Lazy
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||||
import im.vector.matrix.android.api.pushrules.PushRuleService
|
import im.vector.matrix.android.api.pushrules.PushRuleService
|
||||||
@ -52,34 +53,34 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
|
|||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val liveEntityObservers: Set<@JvmSuppressWildcards LiveEntityObserver>,
|
private val liveEntityObservers: Set<@JvmSuppressWildcards LiveEntityObserver>,
|
||||||
private val sessionListeners: SessionListeners,
|
private val sessionListeners: SessionListeners,
|
||||||
private val roomService: RoomService,
|
private val roomService: Lazy<RoomService>,
|
||||||
private val roomDirectoryService: RoomDirectoryService,
|
private val roomDirectoryService: Lazy<RoomDirectoryService>,
|
||||||
private val groupService: GroupService,
|
private val groupService: Lazy<GroupService>,
|
||||||
private val userService: UserService,
|
private val userService: Lazy<UserService>,
|
||||||
private val filterService: FilterService,
|
private val filterService: Lazy<FilterService>,
|
||||||
private val cacheService: CacheService,
|
private val cacheService: Lazy<CacheService>,
|
||||||
private val signOutService: SignOutService,
|
private val signOutService: Lazy<SignOutService>,
|
||||||
private val pushRuleService: PushRuleService,
|
private val pushRuleService: Lazy<PushRuleService>,
|
||||||
private val pushersService: PushersService,
|
private val pushersService: Lazy<PushersService>,
|
||||||
private val cryptoService: CryptoManager,
|
private val cryptoService: Lazy<CryptoManager>,
|
||||||
private val fileService: FileService,
|
private val fileService: Lazy<FileService>,
|
||||||
private val syncThread: SyncThread,
|
private val syncThread: SyncThread,
|
||||||
private val contentUrlResolver: ContentUrlResolver,
|
private val contentUrlResolver: ContentUrlResolver,
|
||||||
private val contentUploadProgressTracker: ContentUploadStateTracker,
|
private val contentUploadProgressTracker: ContentUploadStateTracker,
|
||||||
private val initialSyncProgressService: InitialSyncProgressService)
|
private val initialSyncProgressService: Lazy<InitialSyncProgressService>)
|
||||||
: Session,
|
: Session,
|
||||||
RoomService by roomService,
|
RoomService by roomService.get(),
|
||||||
RoomDirectoryService by roomDirectoryService,
|
RoomDirectoryService by roomDirectoryService.get(),
|
||||||
GroupService by groupService,
|
GroupService by groupService.get(),
|
||||||
UserService by userService,
|
UserService by userService.get(),
|
||||||
CryptoService by cryptoService,
|
CryptoService by cryptoService.get(),
|
||||||
CacheService by cacheService,
|
CacheService by cacheService.get(),
|
||||||
SignOutService by signOutService,
|
SignOutService by signOutService.get(),
|
||||||
FilterService by filterService,
|
FilterService by filterService.get(),
|
||||||
PushRuleService by pushRuleService,
|
PushRuleService by pushRuleService.get(),
|
||||||
PushersService by pushersService,
|
PushersService by pushersService.get(),
|
||||||
FileService by fileService,
|
FileService by fileService.get(),
|
||||||
InitialSyncProgressService by initialSyncProgressService {
|
InitialSyncProgressService by initialSyncProgressService.get() {
|
||||||
|
|
||||||
private var isOpen = false
|
private var isOpen = false
|
||||||
|
|
||||||
@ -123,7 +124,7 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
|
|||||||
assert(isOpen)
|
assert(isOpen)
|
||||||
stopSync()
|
stopSync()
|
||||||
liveEntityObservers.forEach { it.dispose() }
|
liveEntityObservers.forEach { it.dispose() }
|
||||||
cryptoService.close()
|
cryptoService.get().close()
|
||||||
isOpen = false
|
isOpen = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,15 +141,15 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
|
|||||||
//syncThread.kill()
|
//syncThread.kill()
|
||||||
|
|
||||||
Timber.w("SIGN_OUT: call webservice")
|
Timber.w("SIGN_OUT: call webservice")
|
||||||
return signOutService.signOut(object : MatrixCallback<Unit> {
|
return signOutService.get().signOut(object : MatrixCallback<Unit> {
|
||||||
override fun onSuccess(data: Unit) {
|
override fun onSuccess(data: Unit) {
|
||||||
Timber.w("SIGN_OUT: call webservice -> SUCCESS: clear cache")
|
Timber.w("SIGN_OUT: call webservice -> SUCCESS: clear cache")
|
||||||
|
|
||||||
// Clear the cache
|
// Clear the cache
|
||||||
cacheService.clearCache(object : MatrixCallback<Unit> {
|
cacheService.get().clearCache(object : MatrixCallback<Unit> {
|
||||||
override fun onSuccess(data: Unit) {
|
override fun onSuccess(data: Unit) {
|
||||||
Timber.w("SIGN_OUT: clear cache -> SUCCESS: clear crypto cache")
|
Timber.w("SIGN_OUT: clear cache -> SUCCESS: clear crypto cache")
|
||||||
cryptoService.clearCryptoCache(MatrixCallbackDelegate(callback))
|
cryptoService.get().clearCryptoCache(MatrixCallbackDelegate(callback))
|
||||||
|
|
||||||
WorkManagerUtil.cancelAllWorks(context)
|
WorkManagerUtil.cancelAllWorks(context)
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,20 @@ import androidx.work.WorkManager
|
|||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
import im.vector.matrix.android.api.auth.data.Credentials
|
||||||
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
||||||
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
import im.vector.matrix.android.internal.database.model.GroupEntity
|
import im.vector.matrix.android.internal.database.model.GroupEntity
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.di.SessionDatabase
|
import im.vector.matrix.android.internal.di.SessionDatabase
|
||||||
|
import im.vector.matrix.android.internal.session.room.prune.PruneEventTask
|
||||||
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
import im.vector.matrix.android.internal.worker.WorkManagerUtil
|
import im.vector.matrix.android.internal.worker.WorkManagerUtil
|
||||||
import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder
|
import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder
|
||||||
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
||||||
|
import io.realm.OrderedCollectionChangeSet
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
|
import io.realm.RealmResults
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
|
private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
|
||||||
@ -40,8 +47,12 @@ internal class GroupSummaryUpdater @Inject constructor(private val context: Cont
|
|||||||
|
|
||||||
override val query = Monarchy.Query<GroupEntity> { GroupEntity.where(it) }
|
override val query = Monarchy.Query<GroupEntity> { GroupEntity.where(it) }
|
||||||
|
|
||||||
override fun processChanges(inserted: List<GroupEntity>, updated: List<GroupEntity>, deleted: List<GroupEntity>) {
|
override fun onChange(results: RealmResults<GroupEntity>, changeSet: OrderedCollectionChangeSet) {
|
||||||
val newGroupIds = inserted.map { it.groupId }
|
val newGroupIds = changeSet.insertions
|
||||||
|
.asSequence()
|
||||||
|
.mapNotNull { results[it]?.groupId}
|
||||||
|
.toList()
|
||||||
|
|
||||||
val getGroupDataWorkerParams = GetGroupDataWorker.Params(credentials.userId, newGroupIds)
|
val getGroupDataWorkerParams = GetGroupDataWorker.Params(credentials.userId, newGroupIds)
|
||||||
val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams)
|
val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams)
|
||||||
|
|
||||||
@ -55,5 +66,4 @@ internal class GroupSummaryUpdater @Inject constructor(private val context: Cont
|
|||||||
.enqueue()
|
.enqueue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -25,7 +25,9 @@ import im.vector.matrix.android.internal.database.query.types
|
|||||||
import im.vector.matrix.android.internal.di.SessionDatabase
|
import im.vector.matrix.android.internal.di.SessionDatabase
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
|
import io.realm.OrderedCollectionChangeSet
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
|
import io.realm.RealmResults
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -50,19 +52,18 @@ internal class EventRelationsAggregationUpdater @Inject constructor(@SessionData
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun processChanges(inserted: List<EventEntity>, updated: List<EventEntity>, deleted: List<EventEntity>) {
|
override fun onChange(results: RealmResults<EventEntity>, changeSet: OrderedCollectionChangeSet) {
|
||||||
Timber.v("EventRelationsAggregationUpdater called with ${inserted.size} insertions")
|
Timber.v("EventRelationsAggregationUpdater called with ${changeSet.insertions.size} insertions")
|
||||||
val domainInserted = inserted
|
|
||||||
.map { it.asDomain() }
|
|
||||||
|
|
||||||
|
val insertedDomains = changeSet.insertions
|
||||||
|
.asSequence()
|
||||||
|
.mapNotNull { results[it]?.asDomain() }
|
||||||
|
.toList()
|
||||||
val params = EventRelationsAggregationTask.Params(
|
val params = EventRelationsAggregationTask.Params(
|
||||||
domainInserted,
|
insertedDomains,
|
||||||
credentials.userId
|
credentials.userId
|
||||||
)
|
)
|
||||||
|
task.configureWith(params).executeBy(taskExecutor)
|
||||||
task.configureWith(params)
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,9 +26,12 @@ import im.vector.matrix.android.internal.database.query.types
|
|||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.di.SessionDatabase
|
import im.vector.matrix.android.internal.di.SessionDatabase
|
||||||
import im.vector.matrix.android.internal.session.SessionScope
|
import im.vector.matrix.android.internal.session.SessionScope
|
||||||
|
import im.vector.matrix.android.internal.session.room.EventRelationsAggregationTask
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
|
import io.realm.OrderedCollectionChangeSet
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
|
import io.realm.RealmResults
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -44,18 +47,19 @@ internal class EventsPruner @Inject constructor(@SessionDatabase realmConfigurat
|
|||||||
|
|
||||||
override val query = Monarchy.Query<EventEntity> { EventEntity.types(it, listOf(EventType.REDACTION)) }
|
override val query = Monarchy.Query<EventEntity> { EventEntity.types(it, listOf(EventType.REDACTION)) }
|
||||||
|
|
||||||
override fun processChanges(inserted: List<EventEntity>, updated: List<EventEntity>, deleted: List<EventEntity>) {
|
override fun onChange(results: RealmResults<EventEntity>, changeSet: OrderedCollectionChangeSet) {
|
||||||
Timber.v("Event pruner called with ${inserted.size} insertions")
|
Timber.v("Event pruner called with ${changeSet.insertions.size} insertions")
|
||||||
val redactionEvents = inserted.map { it.asDomain() }
|
|
||||||
|
val insertedDomains = changeSet.insertions
|
||||||
|
.asSequence()
|
||||||
|
.mapNotNull { results[it]?.asDomain() }
|
||||||
|
.toList()
|
||||||
|
|
||||||
val params = PruneEventTask.Params(
|
val params = PruneEventTask.Params(
|
||||||
redactionEvents,
|
insertedDomains,
|
||||||
credentials.userId
|
credentials.userId
|
||||||
)
|
)
|
||||||
|
pruneEventTask.configureWith(params).executeBy(taskExecutor)
|
||||||
pruneEventTask.configureWith(params)
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -43,7 +43,7 @@ import kotlin.collections.ArrayList
|
|||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
|
|
||||||
private const val INITIAL_LOAD_SIZE = 20
|
private const val INITIAL_LOAD_SIZE = 10
|
||||||
private const val MIN_FETCHING_COUNT = 30
|
private const val MIN_FETCHING_COUNT = 30
|
||||||
private const val DISPLAY_INDEX_UNKNOWN = Int.MIN_VALUE
|
private const val DISPLAY_INDEX_UNKNOWN = Int.MIN_VALUE
|
||||||
|
|
||||||
@ -216,6 +216,7 @@ internal class DefaultTimeline(
|
|||||||
backgroundRealm.set(realm)
|
backgroundRealm.set(realm)
|
||||||
clearUnlinkedEvents(realm)
|
clearUnlinkedEvents(realm)
|
||||||
|
|
||||||
|
|
||||||
roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst()?.also {
|
roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst()?.also {
|
||||||
it.sendingTimelineEvents.addChangeListener { _ ->
|
it.sendingTimelineEvents.addChangeListener { _ ->
|
||||||
postSnapshot()
|
postSnapshot()
|
||||||
@ -242,6 +243,8 @@ internal class DefaultTimeline(
|
|||||||
Timber.v("Dispose timeline for roomId: $roomId and eventId: $initialEventId")
|
Timber.v("Dispose timeline for roomId: $roomId and eventId: $initialEventId")
|
||||||
BACKGROUND_HANDLER.post {
|
BACKGROUND_HANDLER.post {
|
||||||
cancelableBag.cancel()
|
cancelableBag.cancel()
|
||||||
|
roomEntity?.sendingTimelineEvents?.removeAllChangeListeners()
|
||||||
|
eventRelations.removeAllChangeListeners()
|
||||||
liveEvents.removeAllChangeListeners()
|
liveEvents.removeAllChangeListeners()
|
||||||
backgroundRealm.getAndSet(null).also {
|
backgroundRealm.getAndSet(null).also {
|
||||||
it.close()
|
it.close()
|
||||||
|
@ -105,8 +105,8 @@ open class SyncService : Service() {
|
|||||||
Timber.v("Execute sync request with timeout 0")
|
Timber.v("Execute sync request with timeout 0")
|
||||||
val params = SyncTask.Params(TIME_OUT)
|
val params = SyncTask.Params(TIME_OUT)
|
||||||
cancelableTask = syncTask.configureWith(params)
|
cancelableTask = syncTask.configureWith(params)
|
||||||
.callbackOn(TaskThread.CALLER)
|
.callbackOn(TaskThread.SYNC)
|
||||||
.executeOn(TaskThread.CALLER)
|
.executeOn(TaskThread.SYNC)
|
||||||
.dispatchTo(object : MatrixCallback<Unit> {
|
.dispatchTo(object : MatrixCallback<Unit> {
|
||||||
override fun onSuccess(data: Unit) {
|
override fun onSuccess(data: Unit) {
|
||||||
cancelableTask = null
|
cancelableTask = null
|
||||||
|
@ -97,8 +97,8 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
|
|||||||
val latch = CountDownLatch(1)
|
val latch = CountDownLatch(1)
|
||||||
val params = SyncTask.Params(DEFAULT_LONG_POOL_TIMEOUT)
|
val params = SyncTask.Params(DEFAULT_LONG_POOL_TIMEOUT)
|
||||||
cancelableTask = syncTask.configureWith(params)
|
cancelableTask = syncTask.configureWith(params)
|
||||||
.callbackOn(TaskThread.CALLER)
|
.callbackOn(TaskThread.SYNC)
|
||||||
.executeOn(TaskThread.CALLER)
|
.executeOn(TaskThread.SYNC)
|
||||||
.dispatchTo(object : MatrixCallback<Unit> {
|
.dispatchTo(object : MatrixCallback<Unit> {
|
||||||
override fun onSuccess(data: Unit) {
|
override fun onSuccess(data: Unit) {
|
||||||
latch.countDown()
|
latch.countDown()
|
||||||
|
@ -62,8 +62,8 @@ internal class SyncWorker(context: Context,
|
|||||||
val latch = CountDownLatch(1)
|
val latch = CountDownLatch(1)
|
||||||
val taskParams = SyncTask.Params(0)
|
val taskParams = SyncTask.Params(0)
|
||||||
cancelableTask = syncTask.configureWith(taskParams)
|
cancelableTask = syncTask.configureWith(taskParams)
|
||||||
.callbackOn(TaskThread.CALLER)
|
.callbackOn(TaskThread.SYNC)
|
||||||
.executeOn(TaskThread.CALLER)
|
.executeOn(TaskThread.SYNC)
|
||||||
.dispatchTo(object : MatrixCallback<Unit> {
|
.dispatchTo(object : MatrixCallback<Unit> {
|
||||||
override fun onSuccess(data: Unit) {
|
override fun onSuccess(data: Unit) {
|
||||||
latch.countDown()
|
latch.countDown()
|
||||||
|
@ -22,13 +22,13 @@ import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
|||||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntityFields
|
import im.vector.matrix.android.internal.database.model.EventEntityFields
|
||||||
import im.vector.matrix.android.internal.database.query.types
|
import im.vector.matrix.android.internal.database.query.types
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
|
||||||
import im.vector.matrix.android.internal.di.SessionDatabase
|
import im.vector.matrix.android.internal.di.SessionDatabase
|
||||||
import im.vector.matrix.android.internal.session.SessionScope
|
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.TaskThread
|
import im.vector.matrix.android.internal.task.TaskThread
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
|
import io.realm.OrderedCollectionChangeSet
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
|
import io.realm.RealmResults
|
||||||
import io.realm.Sort
|
import io.realm.Sort
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -42,15 +42,19 @@ internal class UserEntityUpdater @Inject constructor(@SessionDatabase realmConfi
|
|||||||
.types(it, listOf(EventType.STATE_ROOM_MEMBER))
|
.types(it, listOf(EventType.STATE_ROOM_MEMBER))
|
||||||
.sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING)
|
.sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING)
|
||||||
.distinct(EventEntityFields.STATE_KEY)
|
.distinct(EventEntityFields.STATE_KEY)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun processChanges(inserted: List<EventEntity>, updated: List<EventEntity>, deleted: List<EventEntity>) {
|
override fun onChange(results: RealmResults<EventEntity>, changeSet: OrderedCollectionChangeSet) {
|
||||||
val roomMembersEvents = inserted.map { it.eventId }
|
val roomMembersEvents = changeSet.insertions
|
||||||
|
.asSequence()
|
||||||
|
.mapNotNull { results[it]?.eventId }
|
||||||
|
.toList()
|
||||||
|
|
||||||
val taskParams = UpdateUserTask.Params(roomMembersEvents)
|
val taskParams = UpdateUserTask.Params(roomMembersEvents)
|
||||||
updateUserTask
|
updateUserTask
|
||||||
.configureWith(taskParams)
|
.configureWith(taskParams)
|
||||||
.executeOn(TaskThread.IO)
|
.executeOn(TaskThread.IO)
|
||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -77,6 +77,7 @@ internal class TaskExecutor @Inject constructor(private val coroutineDispatchers
|
|||||||
TaskThread.IO -> coroutineDispatchers.io
|
TaskThread.IO -> coroutineDispatchers.io
|
||||||
TaskThread.CALLER -> EmptyCoroutineContext
|
TaskThread.CALLER -> EmptyCoroutineContext
|
||||||
TaskThread.CRYPTO -> coroutineDispatchers.crypto
|
TaskThread.CRYPTO -> coroutineDispatchers.crypto
|
||||||
|
TaskThread.SYNC -> coroutineDispatchers.sync
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,5 +21,6 @@ internal enum class TaskThread {
|
|||||||
COMPUTATION,
|
COMPUTATION,
|
||||||
IO,
|
IO,
|
||||||
CALLER,
|
CALLER,
|
||||||
CRYPTO
|
CRYPTO,
|
||||||
|
SYNC
|
||||||
}
|
}
|
@ -22,5 +22,6 @@ internal data class MatrixCoroutineDispatchers(
|
|||||||
val io: CoroutineDispatcher,
|
val io: CoroutineDispatcher,
|
||||||
val computation: CoroutineDispatcher,
|
val computation: CoroutineDispatcher,
|
||||||
val main: CoroutineDispatcher,
|
val main: CoroutineDispatcher,
|
||||||
val crypto: CoroutineDispatcher
|
val crypto: CoroutineDispatcher,
|
||||||
|
val sync: CoroutineDispatcher
|
||||||
)
|
)
|
@ -18,6 +18,7 @@ package im.vector.riotx.features.home.room.detail.timeline
|
|||||||
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import android.util.LongSparseArray
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListUpdateCallback
|
import androidx.recyclerview.widget.ListUpdateCallback
|
||||||
@ -82,8 +83,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Tim
|
|||||||
fun onUrlLongClicked(url: String): Boolean
|
fun onUrlLongClicked(url: String): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
private val collapsedEventIds = linkedSetOf<String>()
|
private val collapsedEventIds = linkedSetOf<Long>()
|
||||||
private val mergeItemCollapseStates = HashMap<String, Boolean>()
|
private val mergeItemCollapseStates = HashMap<Long,Boolean>()
|
||||||
private val modelCache = arrayListOf<CacheItemData?>()
|
private val modelCache = arrayListOf<CacheItemData?>()
|
||||||
|
|
||||||
private var currentSnapshot: List<TimelineEvent> = emptyList()
|
private var currentSnapshot: List<TimelineEvent> = emptyList()
|
||||||
@ -298,7 +299,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Tim
|
|||||||
} else {
|
} else {
|
||||||
collapsedEventIds.removeAll(mergedEventIds)
|
collapsedEventIds.removeAll(mergedEventIds)
|
||||||
}
|
}
|
||||||
val mergeId = mergedEventIds.joinToString(separator = "_") { it }
|
val mergeId = mergedEventIds.joinToString(separator = "_") { it.toString() }
|
||||||
MergedHeaderItem(isCollapsed, mergeId, mergedData, avatarRenderer) {
|
MergedHeaderItem(isCollapsed, mergeId, mergedData, avatarRenderer) {
|
||||||
mergeItemCollapseStates[event.localId] = it
|
mergeItemCollapseStates[event.localId] = it
|
||||||
requestModelBuild()
|
requestModelBuild()
|
||||||
@ -329,7 +330,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Tim
|
|||||||
}
|
}
|
||||||
|
|
||||||
private data class CacheItemData(
|
private data class CacheItemData(
|
||||||
val localId: String,
|
val localId: Long,
|
||||||
val eventId: String?,
|
val eventId: String?,
|
||||||
val eventModel: EpoxyModel<*>? = null,
|
val eventModel: EpoxyModel<*>? = null,
|
||||||
val mergedHeaderModel: MergedHeaderItem? = null,
|
val mergedHeaderModel: MergedHeaderItem? = null,
|
||||||
|
@ -78,7 +78,7 @@ data class MergedHeaderItem(private val isCollapsed: Boolean,
|
|||||||
}
|
}
|
||||||
|
|
||||||
data class Data(
|
data class Data(
|
||||||
val eventId: String,
|
val eventId: Long,
|
||||||
val userId: String,
|
val userId: String,
|
||||||
val memberName: String,
|
val memberName: String,
|
||||||
val avatarUrl: String?
|
val avatarUrl: String?
|
||||||
|
Loading…
Reference in New Issue
Block a user