From 19202cfca6874856b8191864a878861ca75fb978 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 1 Jul 2019 20:05:48 +0200 Subject: [PATCH 1/6] Perf: try to get better --- .../android/internal/crypto/CryptoManager.kt | 5 +- .../DefaultSasVerificationService.kt | 7 +- .../notification/DefaultPushRuleService.kt | 53 +------------- .../session/pushers/DefaultPusherService.kt | 16 ----- .../session/pushers/GetPushRulesTask.kt | 70 ++++++++++++++++-- .../session/pushers/GetPushersTask.kt | 30 ++++++-- .../action/MessageActionsViewModel.kt | 5 +- .../timeline/factory/MessageItemFactory.kt | 71 ++++++++++++------- .../features/settings/VectorLocale.kt | 3 +- 9 files changed, 150 insertions(+), 110 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt index 01506b719b..8f34a0809c 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt @@ -25,6 +25,7 @@ import android.text.TextUtils import arrow.core.Try import com.squareup.moshi.Types import com.zhuinden.monarchy.Monarchy +import dagger.Lazy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.failure.Failure @@ -98,7 +99,7 @@ internal class CryptoManager @Inject constructor( private val olmManager: OlmManager, // The credentials, private val credentials: Credentials, - private val myDeviceInfoHolder: MyDeviceInfoHolder, + private val myDeviceInfoHolder: Lazy, // the crypto store private val cryptoStore: IMXCryptoStore, // Olm device @@ -190,7 +191,7 @@ internal class CryptoManager @Inject constructor( } override fun getMyDevice(): MXDeviceInfo { - return myDeviceInfoHolder.myDevice + return myDeviceInfoHolder.get().myDevice } override fun getDevicesList(callback: MatrixCallback) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultSasVerificationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultSasVerificationService.kt index ebf3294a09..fd4239b6f7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultSasVerificationService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultSasVerificationService.kt @@ -18,6 +18,7 @@ package im.vector.matrix.android.internal.crypto.verification import android.os.Handler import android.os.Looper +import dagger.Lazy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.session.crypto.sas.CancelCode @@ -55,7 +56,7 @@ import kotlin.collections.HashMap @SessionScope internal class DefaultSasVerificationService @Inject constructor(private val credentials: Credentials, private val cryptoStore: IMXCryptoStore, - private val myDeviceInfoHolder: MyDeviceInfoHolder, + private val myDeviceInfoHolder: Lazy, private val deviceListManager: DeviceListManager, private val setDeviceVerificationAction: SetDeviceVerificationAction, private val sendToDeviceTask: SendToDeviceTask, @@ -197,7 +198,7 @@ internal class DefaultSasVerificationService @Inject constructor(private val cre cryptoStore, sendToDeviceTask, taskExecutor, - myDeviceInfoHolder.myDevice.fingerprint()!!, + myDeviceInfoHolder.get().myDevice.fingerprint()!!, startReq.transactionID!!, otherUserId) addTransaction(tx) @@ -366,7 +367,7 @@ internal class DefaultSasVerificationService @Inject constructor(private val cre cryptoStore, sendToDeviceTask, taskExecutor, - myDeviceInfoHolder.myDevice.fingerprint()!!, + myDeviceInfoHolder.get().myDevice.fingerprint()!!, txID, userId, deviceID) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt index e8ef2f7df8..5b21f0e562 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt @@ -48,58 +48,7 @@ internal class DefaultPushRuleService @Inject constructor( override fun fetchPushRules(scope: String) { pushRulesTask - .configureWith(Unit) - .dispatchTo(object : MatrixCallback { - override fun onSuccess(data: GetPushRulesResponse) { - monarchy.runTransactionSync { realm -> - //clear existings? - //TODO - realm.where(PushRulesEntity::class.java) - .equalTo(PusherEntityFields.USER_ID, sessionParams.credentials.userId) - .findAll().deleteAllFromRealm() - - val content = PushRulesEntity(sessionParams.credentials.userId, scope, "content") - data.global.content?.forEach { rule -> - PushRulesMapper.map(rule).also { - content.pushRules.add(it) - } - } - realm.insertOrUpdate(content) - - val override = PushRulesEntity(sessionParams.credentials.userId, scope, "override") - data.global.override?.forEach { rule -> - PushRulesMapper.map(rule).also { - override.pushRules.add(it) - } - } - realm.insertOrUpdate(override) - - val rooms = PushRulesEntity(sessionParams.credentials.userId, scope, "room") - data.global.room?.forEach { rule -> - PushRulesMapper.map(rule).also { - rooms.pushRules.add(it) - } - } - realm.insertOrUpdate(rooms) - - val senders = PushRulesEntity(sessionParams.credentials.userId, scope, "sender") - data.global.sender?.forEach { rule -> - PushRulesMapper.map(rule).also { - senders.pushRules.add(it) - } - } - realm.insertOrUpdate(senders) - - val underrides = PushRulesEntity(sessionParams.credentials.userId, scope, "underride") - data.global.underride?.forEach { rule -> - PushRulesMapper.map(rule).also { - underrides.pushRules.add(it) - } - } - realm.insertOrUpdate(underrides) - } - } - }) + .configureWith(GetPushRulesTask.Params(scope)) .executeBy(taskExecutor) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt index 103bdb71e4..8401f3e628 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt @@ -54,22 +54,6 @@ internal class DefaultPusherService @Inject constructor( override fun refreshPushers() { getPusherTask .configureWith(Unit) - .dispatchTo(object : MatrixCallback { - override fun onSuccess(data: GetPushersResponse) { - monarchy.runTransactionSync { realm -> - //clear existings? - realm.where(PusherEntity::class.java) - .equalTo(PusherEntityFields.USER_ID, sessionParam.credentials.userId) - .findAll().deleteAllFromRealm() - data.pushers?.forEach { jsonPusher -> - jsonPusher.toEntity(sessionParam.credentials.userId).also { - it.state = PusherState.REGISTERED - realm.insertOrUpdate(it) - } - } - } - } - }) .executeBy(taskExecutor) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/GetPushRulesTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/GetPushRulesTask.kt index 46af3b6366..cbd8dcac22 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/GetPushRulesTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/GetPushRulesTask.kt @@ -16,19 +16,81 @@ package im.vector.matrix.android.internal.session.pushers import arrow.core.Try +import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.api.auth.data.SessionParams import im.vector.matrix.android.api.pushrules.rest.GetPushRulesResponse +import im.vector.matrix.android.internal.database.mapper.PushRulesMapper +import im.vector.matrix.android.internal.database.model.PushRulesEntity +import im.vector.matrix.android.internal.database.model.PusherEntityFields import im.vector.matrix.android.internal.network.executeRequest import im.vector.matrix.android.internal.task.Task +import im.vector.matrix.android.internal.util.tryTransactionSync import javax.inject.Inject -internal interface GetPushRulesTask : Task +internal interface GetPushRulesTask : Task { -internal class DefaultGetPushRulesTask @Inject constructor(private val pushRulesApi: PushRulesApi) : GetPushRulesTask { + data class Params(val scope: String) - override suspend fun execute(params: Unit): Try { - return executeRequest { +} + + +internal class DefaultGetPushRulesTask @Inject constructor(private val pushRulesApi: PushRulesApi, + private val monarchy: Monarchy, + private val sessionParams: SessionParams) : GetPushRulesTask { + + override suspend fun execute(params: GetPushRulesTask.Params): Try { + return executeRequest { apiCall = pushRulesApi.getAllRules() + }.flatMap { response -> + val scope = params.scope + return monarchy.tryTransactionSync { realm -> + //clear existings? + //TODO + realm.where(PushRulesEntity::class.java) + .equalTo(PusherEntityFields.USER_ID, sessionParams.credentials.userId) + .findAll().deleteAllFromRealm() + + val content = PushRulesEntity(sessionParams.credentials.userId, scope, "content") + response.global.content?.forEach { rule -> + PushRulesMapper.map(rule).also { + content.pushRules.add(it) + } + } + realm.insertOrUpdate(content) + + val override = PushRulesEntity(sessionParams.credentials.userId, scope, "override") + response.global.override?.forEach { rule -> + PushRulesMapper.map(rule).also { + override.pushRules.add(it) + } + } + realm.insertOrUpdate(override) + + val rooms = PushRulesEntity(sessionParams.credentials.userId, scope, "room") + response.global.room?.forEach { rule -> + PushRulesMapper.map(rule).also { + rooms.pushRules.add(it) + } + } + realm.insertOrUpdate(rooms) + + val senders = PushRulesEntity(sessionParams.credentials.userId, scope, "sender") + response.global.sender?.forEach { rule -> + PushRulesMapper.map(rule).also { + senders.pushRules.add(it) + } + } + realm.insertOrUpdate(senders) + + val underrides = PushRulesEntity(sessionParams.credentials.userId, scope, "underride") + response.global.underride?.forEach { rule -> + PushRulesMapper.map(rule).also { + underrides.pushRules.add(it) + } + } + realm.insertOrUpdate(underrides) + } } } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/GetPushersTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/GetPushersTask.kt index 05b36fb5bc..57ea8a38ba 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/GetPushersTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/GetPushersTask.kt @@ -16,17 +16,39 @@ package im.vector.matrix.android.internal.session.pushers import arrow.core.Try +import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.api.auth.data.SessionParams +import im.vector.matrix.android.api.session.pushers.PusherState +import im.vector.matrix.android.internal.database.mapper.toEntity +import im.vector.matrix.android.internal.database.model.PusherEntity +import im.vector.matrix.android.internal.database.model.PusherEntityFields import im.vector.matrix.android.internal.network.executeRequest import im.vector.matrix.android.internal.task.Task +import im.vector.matrix.android.internal.util.tryTransactionSync import javax.inject.Inject -internal interface GetPushersTask : Task +internal interface GetPushersTask : Task -internal class DefaultGetPusherTask @Inject constructor(private val pushersAPI: PushersAPI) : GetPushersTask { +internal class DefaultGetPusherTask @Inject constructor(private val pushersAPI: PushersAPI, + private val monarchy: Monarchy, + private val sessionParams: SessionParams) : GetPushersTask { - override suspend fun execute(params: Unit): Try { - return executeRequest { + override suspend fun execute(params: Unit): Try { + return executeRequest { apiCall = pushersAPI.getPushers() + }.flatMap { response -> + monarchy.tryTransactionSync { realm -> + //clear existings? + realm.where(PusherEntity::class.java) + .equalTo(PusherEntityFields.USER_ID, sessionParams.credentials.userId) + .findAll().deleteAllFromRealm() + response.pushers?.forEach { jsonPusher -> + jsonPusher.toEntity(sessionParams.credentials.userId).also { + it.state = PusherState.REGISTERED + realm.insertOrUpdate(it) + } + } + } } } } \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsViewModel.kt index 58c8cf61ac..9bd6bda2a1 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsViewModel.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsViewModel.kt @@ -18,6 +18,7 @@ package im.vector.riotredesign.features.home.room.detail.timeline.action import com.airbnb.mvrx.* import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject +import dagger.Lazy import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.toModel @@ -84,7 +85,7 @@ data class MessageActionState( */ class MessageActionsViewModel @AssistedInject constructor(@Assisted initialState: MessageActionState, - private val eventHtmlRenderer: EventHtmlRenderer, + private val eventHtmlRenderer: Lazy, session: Session, private val noticeEventFormatter: NoticeEventFormatter ) : VectorViewModel(initialState) { @@ -121,7 +122,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted } fun resolveBody(state: MessageActionState): CharSequence? { - return state.messageBody(eventHtmlRenderer, noticeEventFormatter) + return state.messageBody(eventHtmlRenderer.get(), noticeEventFormatter) } } \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 5cb7c94346..b8917f1d8d 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -23,12 +23,20 @@ import android.text.style.ClickableSpan import android.text.style.ForegroundColorSpan import android.text.style.RelativeSizeSpan import android.view.View +import dagger.Lazy import im.vector.matrix.android.api.permalinks.MatrixLinkify import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan import im.vector.matrix.android.api.session.events.model.RelationType import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.EditAggregatedSummary -import im.vector.matrix.android.api.session.room.model.message.* +import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent +import im.vector.matrix.android.api.session.room.model.message.MessageContent +import im.vector.matrix.android.api.session.room.model.message.MessageEmoteContent +import im.vector.matrix.android.api.session.room.model.message.MessageFileContent +import im.vector.matrix.android.api.session.room.model.message.MessageImageContent +import im.vector.matrix.android.api.session.room.model.message.MessageNoticeContent +import im.vector.matrix.android.api.session.room.model.message.MessageTextContent +import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent import im.vector.matrix.android.api.session.room.send.SendState import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.riotredesign.EmojiCompatFontProvider @@ -42,7 +50,18 @@ import im.vector.riotredesign.features.home.AvatarRenderer import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController import im.vector.riotredesign.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider -import im.vector.riotredesign.features.home.room.detail.timeline.item.* +import im.vector.riotredesign.features.home.room.detail.timeline.item.BlankItem_ +import im.vector.riotredesign.features.home.room.detail.timeline.item.DefaultItem +import im.vector.riotredesign.features.home.room.detail.timeline.item.DefaultItem_ +import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageFileItem +import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageFileItem_ +import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageImageVideoItem +import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageImageVideoItem_ +import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData +import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageTextItem +import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageTextItem_ +import im.vector.riotredesign.features.home.room.detail.timeline.item.RedactedMessageItem +import im.vector.riotredesign.features.home.room.detail.timeline.item.RedactedMessageItem_ import im.vector.riotredesign.features.home.room.detail.timeline.util.MessageInformationDataFactory import im.vector.riotredesign.features.html.EventHtmlRenderer import im.vector.riotredesign.features.media.ImageContentRenderer @@ -54,7 +73,7 @@ class MessageItemFactory @Inject constructor( private val avatarRenderer: AvatarRenderer, private val colorProvider: ColorProvider, private val timelineMediaSizeProvider: TimelineMediaSizeProvider, - private val htmlRenderer: EventHtmlRenderer, + private val htmlRenderer: Lazy, private val stringProvider: StringProvider, private val emojiCompatFontProvider: EmojiCompatFontProvider, private val imageContentRenderer: ImageContentRenderer, @@ -78,9 +97,9 @@ class MessageItemFactory @Inject constructor( val messageContent: MessageContent = event.annotations?.editSummary?.aggregatedContent?.toModel() - ?: event.root.getClearContent().toModel() - ?: //Malformed content, we should echo something on screen - return DefaultItem_().text(stringProvider.getString(R.string.malformed_message)) + ?: event.root.getClearContent().toModel() + ?: //Malformed content, we should echo something on screen + return DefaultItem_().text(stringProvider.getString(R.string.malformed_message)) if (messageContent.relatesTo?.type == RelationType.REPLACE) { // ignore replace event, the targeted id is already edited @@ -90,16 +109,16 @@ class MessageItemFactory @Inject constructor( // val ev = all.toModel() return when (messageContent) { is MessageEmoteContent -> buildEmoteMessageItem(messageContent, - informationData, - event.annotations?.editSummary, - highlight, - callback) + informationData, + event.annotations?.editSummary, + highlight, + callback) is MessageTextContent -> buildTextMessageItem(event.sendState, - messageContent, - informationData, - event.annotations?.editSummary, - highlight, - callback + messageContent, + informationData, + event.annotations?.editSummary, + highlight, + callback ) is MessageImageContent -> buildImageMessageItem(messageContent, informationData, highlight, callback) is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, highlight, callback) @@ -133,7 +152,7 @@ class MessageItemFactory @Inject constructor( })) .longClickListener { view -> return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view) - ?: false + ?: false } } @@ -156,7 +175,7 @@ class MessageItemFactory @Inject constructor( })) .longClickListener { view -> return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view) - ?: false + ?: false } .clickListener( DebouncedClickListener(View.OnClickListener { _ -> @@ -208,7 +227,7 @@ class MessageItemFactory @Inject constructor( })) .longClickListener { view -> return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view) - ?: false + ?: false } } @@ -251,7 +270,7 @@ class MessageItemFactory @Inject constructor( .clickListener { view -> callback?.onVideoMessageClicked(messageContent, videoData, view) } .longClickListener { view -> return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view) - ?: false + ?: false } } @@ -263,7 +282,7 @@ class MessageItemFactory @Inject constructor( callback: TimelineEventController.Callback?): MessageTextItem? { val bodyToUse = messageContent.formattedBody?.let { - htmlRenderer.render(it.trim()) + htmlRenderer.get().render(it.trim()) } ?: messageContent.body val linkifiedBody = linkifyBody(bodyToUse, callback) @@ -291,7 +310,7 @@ class MessageItemFactory @Inject constructor( })) .longClickListener { view -> return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view) - ?: false + ?: false } } @@ -323,9 +342,9 @@ class MessageItemFactory @Inject constructor( //nop } }, - editStart, - editEnd, - Spanned.SPAN_INCLUSIVE_EXCLUSIVE) + editStart, + editEnd, + Spanned.SPAN_INCLUSIVE_EXCLUSIVE) return spannable } @@ -361,7 +380,7 @@ class MessageItemFactory @Inject constructor( })) .longClickListener { view -> return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view) - ?: false + ?: false } } @@ -397,7 +416,7 @@ class MessageItemFactory @Inject constructor( })) .longClickListener { view -> return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view) - ?: false + ?: false } } diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorLocale.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorLocale.kt index 0c88f508bb..b5faddf97e 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorLocale.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorLocale.kt @@ -24,6 +24,7 @@ import android.text.TextUtils import android.util.Pair import androidx.core.content.edit import im.vector.riotredesign.R +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import timber.log.Timber @@ -75,7 +76,7 @@ object VectorLocale { } // init the known locales in background, using kotlin coroutines - GlobalScope.launch { + GlobalScope.launch(Dispatchers.IO) { initApplicationLocales(context) } } From de9a5a3d12c29aba5efa15bcb6b01fc364276d81 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 1 Jul 2019 20:19:50 +0200 Subject: [PATCH 2/6] Perf: eventHtmlRenderer is slow to build, get only one instance --- .../riotredesign/core/di/VectorComponent.kt | 3 +++ .../features/html/EventHtmlRenderer.kt | 19 ++++++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt index ffc3a126e9..1ae004c3ae 100644 --- a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt +++ b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt @@ -33,6 +33,7 @@ import im.vector.riotredesign.features.home.AvatarRenderer import im.vector.riotredesign.features.home.HomeNavigator import im.vector.riotredesign.features.home.HomeRoomListObservableStore import im.vector.riotredesign.features.home.group.SelectedGroupStore +import im.vector.riotredesign.features.html.EventHtmlRenderer import im.vector.riotredesign.features.navigation.Navigator import im.vector.riotredesign.features.notifications.NotifiableEventResolver import im.vector.riotredesign.features.notifications.NotificationBroadcastReceiver @@ -68,6 +69,8 @@ interface VectorComponent { fun emojiCompatFontProvider(): EmojiCompatFontProvider + fun eventHtmlRenderer(): EventHtmlRenderer + fun navigator(): Navigator fun homeNavigator(): HomeNavigator diff --git a/vector/src/main/java/im/vector/riotredesign/features/html/EventHtmlRenderer.kt b/vector/src/main/java/im/vector/riotredesign/features/html/EventHtmlRenderer.kt index fa755a1136..15beae6ba7 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/html/EventHtmlRenderer.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/html/EventHtmlRenderer.kt @@ -18,10 +18,9 @@ package im.vector.riotredesign.features.html import android.content.Context import android.text.style.URLSpan -import androidx.appcompat.app.AppCompatActivity import im.vector.matrix.android.api.permalinks.PermalinkData import im.vector.matrix.android.api.permalinks.PermalinkParser -import im.vector.matrix.android.api.session.Session +import im.vector.riotredesign.core.di.ActiveSessionHolder import im.vector.riotredesign.core.glide.GlideApp import im.vector.riotredesign.core.glide.GlideRequests import im.vector.riotredesign.features.home.AvatarRenderer @@ -37,12 +36,14 @@ import ru.noties.markwon.html.TagHandler import ru.noties.markwon.html.tag.* import java.util.Arrays.asList import javax.inject.Inject +import javax.inject.Singleton -class EventHtmlRenderer @Inject constructor(context: AppCompatActivity, +@Singleton +class EventHtmlRenderer @Inject constructor(context: Context, val avatarRenderer: AvatarRenderer, - session: Session) { + sessionHolder: ActiveSessionHolder) { private val markwon = Markwon.builder(context) - .usePlugin(MatrixPlugin.create(GlideApp.with(context), context, avatarRenderer, session)) + .usePlugin(MatrixPlugin.create(GlideApp.with(context), context, avatarRenderer, sessionHolder)) .build() fun render(text: String): CharSequence { @@ -54,7 +55,7 @@ class EventHtmlRenderer @Inject constructor(context: AppCompatActivity, private class MatrixPlugin private constructor(private val glideRequests: GlideRequests, private val context: Context, private val avatarRenderer: AvatarRenderer, - private val session: Session) : AbstractMarkwonPlugin() { + private val session: ActiveSessionHolder) : AbstractMarkwonPlugin() { override fun configureConfiguration(builder: MarkwonConfiguration.Builder) { builder.htmlParser(MarkwonHtmlParserImpl.create()) @@ -122,7 +123,7 @@ private class MatrixPlugin private constructor(private val glideRequests: GlideR companion object { - fun create(glideRequests: GlideRequests, context: Context, avatarRenderer: AvatarRenderer, session: Session): MatrixPlugin { + fun create(glideRequests: GlideRequests, context: Context, avatarRenderer: AvatarRenderer, session: ActiveSessionHolder): MatrixPlugin { return MatrixPlugin(glideRequests, context, avatarRenderer, session) } } @@ -131,7 +132,7 @@ private class MatrixPlugin private constructor(private val glideRequests: GlideR private class MxLinkHandler(private val glideRequests: GlideRequests, private val context: Context, private val avatarRenderer: AvatarRenderer, - private val session: Session) : TagHandler() { + private val sessionHolder: ActiveSessionHolder) : TagHandler() { private val linkHandler = LinkHandler() @@ -141,7 +142,7 @@ private class MxLinkHandler(private val glideRequests: GlideRequests, val permalinkData = PermalinkParser.parse(link) when (permalinkData) { is PermalinkData.UserLink -> { - val user = session.getUser(permalinkData.userId) + val user = sessionHolder.getSafeActiveSession()?.getUser(permalinkData.userId) val span = PillImageSpan(glideRequests, avatarRenderer, context, permalinkData.userId, user) SpannableBuilder.setSpans( visitor.builder(), From 41ed4b23d82adc7821d4baeefa7051015bd0260c Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 2 Jul 2019 09:39:45 +0200 Subject: [PATCH 3/6] Update dependencies (tested ok) --- matrix-sdk-android-rx/build.gradle | 8 ++++---- matrix-sdk-android/build.gradle | 20 +++++++++---------- vector/build.gradle | 14 ++++++------- .../settings/VectorSettingsActivity.kt | 4 +--- 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/matrix-sdk-android-rx/build.gradle b/matrix-sdk-android-rx/build.gradle index 183f3be1a1..546922f25b 100644 --- a/matrix-sdk-android-rx/build.gradle +++ b/matrix-sdk-android-rx/build.gradle @@ -35,11 +35,11 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(":matrix-sdk-android") - implementation 'androidx.appcompat:appcompat:1.1.0-alpha01' + implementation 'androidx.appcompat:appcompat:1.1.0-beta01' implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0' - implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' + implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 49a5bd381a..1bcd4fb3c6 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -86,7 +86,7 @@ static def gitRevisionDate() { dependencies { def arrow_version = "0.8.0" - def support_version = '1.1.0-alpha03' + def support_version = '1.1.0-beta01' def moshi_version = '1.8.0' def lifecycle_version = '2.0.0' def coroutines_version = "1.0.1" @@ -98,8 +98,8 @@ dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" - implementation "androidx.appcompat:appcompat:$support_version" - implementation "androidx.recyclerview:recyclerview:$support_version" + implementation "androidx.appcompat:appcompat:1.1.0-beta01" + implementation "androidx.recyclerview:recyclerview:1.1.0-alpha06" implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" @@ -107,7 +107,7 @@ dependencies { // Network implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-moshi:2.4.0' - implementation 'com.squareup.okhttp3:okhttp:3.11.0' + implementation 'com.squareup.okhttp3:okhttp:3.14.1' implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0' implementation 'com.novoda:merlin:1.1.6' implementation "com.squareup.moshi:moshi-adapters:$moshi_version" @@ -120,7 +120,7 @@ dependencies { kapt 'dk.ilios:realmfieldnameshelper:1.1.1' // Work - implementation "androidx.work:work-runtime-ktx:2.1.0-beta01" + implementation "androidx.work:work-runtime-ktx:2.1.0-rc01" // FP implementation "io.arrow-kt:arrow-core:$arrow_version" @@ -155,11 +155,11 @@ dependencies { testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" androidTestImplementation "org.koin:koin-test:$koin_version" - androidTestImplementation 'androidx.test:core:1.1.0' - androidTestImplementation 'androidx.test:runner:1.1.1' - androidTestImplementation 'androidx.test:rules:1.1.1' - androidTestImplementation 'androidx.test.ext:junit:1.1.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' + androidTestImplementation 'androidx.test:core:1.2.0' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test:rules:1.2.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' androidTestImplementation 'org.amshove.kluent:kluent-android:1.44' androidTestImplementation "io.mockk:mockk-android:1.8.13.kotlin13" androidTestImplementation "androidx.arch.core:core-testing:$lifecycle_version" diff --git a/vector/build.gradle b/vector/build.gradle index 5e17277f7e..4575c1305d 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -156,9 +156,9 @@ dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" - implementation 'androidx.appcompat:appcompat:1.1.0-alpha03' - implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1' - implementation 'androidx.core:core-ktx:1.0.1' + implementation 'androidx.appcompat:appcompat:1.1.0-beta01' + implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2' + implementation 'androidx.core:core-ktx:1.0.2' implementation 'com.jakewharton.threetenabp:threetenabp:1.1.1' implementation "com.squareup.moshi:moshi-adapters:$moshi_version" @@ -185,7 +185,7 @@ dependencies { implementation 'com.airbnb.android:mvrx:1.0.1' // Work - implementation "androidx.work:work-runtime-ktx:2.1.0-beta01" + implementation "androidx.work:work-runtime-ktx:2.1.0-rc01" // Functional Programming implementation "io.arrow-kt:arrow-core:$arrow_version" @@ -195,7 +195,7 @@ dependencies { // UI implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' - implementation 'com.google.android.material:material:1.1.0-alpha04' + implementation 'com.google.android.material:material:1.1.0-alpha07' implementation 'me.gujun.android:span:1.7' implementation "ru.noties.markwon:core:$markwon_version" implementation "ru.noties.markwon:html:$markwon_version" @@ -246,8 +246,8 @@ dependencies { // TESTS testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' } if (!getGradle().getStartParameter().getTaskRequests().toString().contains("Fdroid")) { diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsActivity.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsActivity.kt index 5207efd5fa..672a33d0fc 100755 --- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsActivity.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsActivity.kt @@ -86,9 +86,7 @@ class VectorSettingsActivity : VectorBaseActivity(), try { pref?.fragment?.let { oFragment = supportFragmentManager.fragmentFactory - .instantiate( - classLoader, - it, pref.extras) + .instantiate(classLoader, it) } } catch (e: Throwable) { showSnackbar(getString(R.string.not_implemented)) From 5b102485bc9c98f54b4c68a64b45757108d9dfa6 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 2 Jul 2019 19:12:20 +0200 Subject: [PATCH 4/6] Perf: timeline should reuse one background looper thread --- .../session/room/timeline/DefaultTimeline.kt | 55 +++++++++++-------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt index 72c07527b6..34de3708da 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt @@ -30,7 +30,12 @@ import im.vector.matrix.android.api.util.addTo import im.vector.matrix.android.internal.crypto.NewSessionListener import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent import im.vector.matrix.android.internal.database.mapper.asDomain -import im.vector.matrix.android.internal.database.model.* +import im.vector.matrix.android.internal.database.model.ChunkEntity +import im.vector.matrix.android.internal.database.model.ChunkEntityFields +import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryEntity +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.RoomEntity import im.vector.matrix.android.internal.database.query.findIncludingEvent import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom import im.vector.matrix.android.internal.database.query.where @@ -38,7 +43,13 @@ import im.vector.matrix.android.internal.database.query.whereInRoom import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.util.Debouncer -import io.realm.* +import io.realm.OrderedCollectionChangeSet +import io.realm.OrderedRealmCollectionChangeListener +import io.realm.Realm +import io.realm.RealmConfiguration +import io.realm.RealmQuery +import io.realm.RealmResults +import io.realm.Sort import timber.log.Timber import java.util.* import java.util.concurrent.atomic.AtomicBoolean @@ -50,7 +61,6 @@ import kotlin.collections.HashMap private const val INITIAL_LOAD_SIZE = 20 private const val MIN_FETCHING_COUNT = 30 private const val DISPLAY_INDEX_UNKNOWN = Int.MIN_VALUE -private const val THREAD_NAME = "TIMELINE_DB_THREAD" internal class DefaultTimeline( private val roomId: String, @@ -64,18 +74,22 @@ internal class DefaultTimeline( private val allowedTypes: List? ) : Timeline { + private companion object { + val BACKGROUND_HANDLER = Handler( + HandlerThread("TIMELINE_DB_THREAD").apply { start() }.looper + ) + } + override var listener: Timeline.Listener? = null set(value) { field = value - backgroundHandler.get()?.post { + BACKGROUND_HANDLER.post { postSnapshot() } } private val isStarted = AtomicBoolean(false) private val isReady = AtomicBoolean(false) - private val backgroundHandlerThread = AtomicReference() - private val backgroundHandler = AtomicReference() private val mainHandler = Handler(Looper.getMainLooper()) private val backgroundRealm = AtomicReference() private val cancelableBag = CancelableBag() @@ -168,14 +182,14 @@ internal class DefaultTimeline( override fun onNewSession(roomId: String?, senderKey: String, sessionId: String) { if (roomId == this@DefaultTimeline.roomId) { Timber.v("New session id detected for this room") - backgroundHandler.get()?.post { + BACKGROUND_HANDLER.post { val realm = backgroundRealm.get() var hasChange = false builtEvents.forEachIndexed { index, timelineEvent -> if (timelineEvent.isEncrypted()) { val eventContent = timelineEvent.root.content.toModel() if (eventContent?.sessionId == sessionId - && (timelineEvent.root.mClearEvent == null || timelineEvent.root.mCryptoError != null)) { + && (timelineEvent.root.mClearEvent == null || timelineEvent.root.mCryptoError != null)) { //we need to rebuild this event EventEntity.where(realm, eventId = timelineEvent.root.eventId!!).findFirst()?.let { builtEvents[index] = timelineEventFactory.create(it, realm) @@ -194,7 +208,7 @@ internal class DefaultTimeline( // Public methods ****************************************************************************** override fun paginate(direction: Timeline.Direction, count: Int) { - backgroundHandler.get()?.post { + BACKGROUND_HANDLER.post { if (!canPaginate(direction)) { return@post } @@ -211,13 +225,8 @@ internal class DefaultTimeline( override fun start() { if (isStarted.compareAndSet(false, true)) { Timber.v("Start timeline for roomId: $roomId and eventId: $initialEventId") - val handlerThread = HandlerThread(THREAD_NAME + hashCode()) - handlerThread.start() - val handler = Handler(handlerThread.looper) - this.backgroundHandlerThread.set(handlerThread) - this.backgroundHandler.set(handler) cryptoService.addNewSessionListener(newSessionListener) - handler.post { + BACKGROUND_HANDLER.post { val realm = Realm.getInstance(realmConfiguration) backgroundRealm.set(realm) clearUnlinkedEvents(realm) @@ -246,14 +255,12 @@ internal class DefaultTimeline( if (isStarted.compareAndSet(true, false)) { cryptoService.removeSessionListener(newSessionListener) Timber.v("Dispose timeline for roomId: $roomId and eventId: $initialEventId") - backgroundHandler.get()?.post { + BACKGROUND_HANDLER.post { cancelableBag.cancel() liveEvents.removeAllChangeListeners() backgroundRealm.getAndSet(null).also { it.close() } - backgroundHandler.set(null) - backgroundHandlerThread.getAndSet(null)?.quit() } } } @@ -387,9 +394,9 @@ internal class DefaultTimeline( private fun executePaginationTask(direction: Timeline.Direction, limit: Int) { val token = getTokenLive(direction) ?: return val params = PaginationTask.Params(roomId = roomId, - from = token, - direction = direction.toPaginationDirection(), - limit = limit) + from = token, + direction = direction.toPaginationDirection(), + limit = limit) Timber.v("Should fetch $limit items $direction") paginationTask.configureWith(params) @@ -400,7 +407,7 @@ internal class DefaultTimeline( Timber.v("Success fetching $limit items $direction from pagination request") } else { // Database won't be updated, so we force pagination request - backgroundHandler.get()?.post { + BACKGROUND_HANDLER.post { executePaginationTask(direction, limit) } } @@ -441,6 +448,7 @@ internal class DefaultTimeline( if (count < 1) { return 0 } + val start = System.currentTimeMillis() val offsetResults = getOffsetResults(startDisplayIndex, direction, count) if (offsetResults.isEmpty()) { return 0 @@ -459,7 +467,8 @@ internal class DefaultTimeline( builtEventsIdMap.entries.filter { it.value >= position }.forEach { it.setValue(it.value + 1) } builtEventsIdMap[eventEntity.eventId] = position } - Timber.v("Built ${offsetResults.size} items from db") + val time = System.currentTimeMillis() - start + Timber.v("Built ${offsetResults.size} items from db in $time ms") return offsetResults.size } From 2f66321c2aa54c86ebb9759defdb1cd6a020635b Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 2 Jul 2019 19:59:01 +0200 Subject: [PATCH 5/6] RoomSummary: don't fetch last event by default as it takes some time --- .../main/java/im/vector/matrix/rx/RxRoom.kt | 4 +-- .../java/im/vector/matrix/rx/RxSession.kt | 4 +-- .../matrix/android/api/session/room/Room.kt | 4 +-- .../android/api/session/room/RoomService.kt | 2 +- .../database/mapper/RoomSummaryMapper.kt | 19 +++++------- .../internal/session/room/DefaultRoom.kt | 30 ++++++++++--------- .../session/room/DefaultRoomService.kt | 4 +-- .../room/timeline/TimelineEventFactory.kt | 2 +- .../features/home/HomeActivityViewModel.kt | 2 +- .../home/room/detail/RoomDetailViewModel.kt | 2 +- .../notifications/NotifiableEventResolver.kt | 6 ++-- .../NotificationBroadcastReceiver.kt | 4 +-- .../roomdirectory/RoomDirectoryViewModel.kt | 2 +- .../roompreview/RoomPreviewViewModel.kt | 2 +- 14 files changed, 42 insertions(+), 45 deletions(-) diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt index 8a137518a4..e209a0ca3b 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt @@ -24,8 +24,8 @@ import io.reactivex.Observable class RxRoom(private val room: Room) { - fun liveRoomSummary(): Observable { - return room.liveRoomSummary.asObservable() + fun liveRoomSummary(fetchLastEvent: Boolean): Observable { + return room.liveRoomSummary(fetchLastEvent).asObservable() } fun liveRoomMemberIds(): Observable> { diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt index af14911644..6490083932 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt @@ -25,8 +25,8 @@ import io.reactivex.Observable class RxSession(private val session: Session) { - fun liveRoomSummaries(): Observable> { - return session.liveRoomSummaries().asObservable() + fun liveRoomSummaries(fetchLastEvents: Boolean): Observable> { + return session.liveRoomSummaries(fetchLastEvents).asObservable() } fun liveGroupSummaries(): Observable> { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt index 3e893a091d..35efa0fb83 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt @@ -47,8 +47,8 @@ interface Room : * A live [RoomSummary] associated with the room * You can observe this summary to get dynamic data from this room. */ - val liveRoomSummary: LiveData + fun liveRoomSummary(fetchLastEvent: Boolean = false): LiveData - val roomSummary: RoomSummary? + fun roomSummary(fetchLastEvent: Boolean = false): RoomSummary? } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt index fc0bf49955..8fd6605f64 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt @@ -43,6 +43,6 @@ interface RoomService { * Get a live list of room summaries. This list is refreshed as soon as the data changes. * @return the [LiveData] of [RoomSummary] */ - fun liveRoomSummaries(): LiveData> + fun liveRoomSummaries(fetchLastEvents: Boolean = true): LiveData> } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt index 0ebb7ebd88..b5fdabc702 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt @@ -16,29 +16,24 @@ package im.vector.matrix.android.internal.database.mapper -import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.tag.RoomTag -import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.internal.database.model.RoomSummaryEntity import im.vector.matrix.android.internal.session.room.timeline.TimelineEventFactory import javax.inject.Inject +internal class RoomSummaryMapper @Inject constructor(private val timelineEventFactory: TimelineEventFactory) { -internal class RoomSummaryMapper @Inject constructor( - private val timelineEventFactory: TimelineEventFactory, - private val monarchy: Monarchy) { - - fun map(roomSummaryEntity: RoomSummaryEntity): RoomSummary { + fun map(roomSummaryEntity: RoomSummaryEntity, getLatestEvent: Boolean = false): RoomSummary { val tags = roomSummaryEntity.tags.map { RoomTag(it.tagName, it.tagOrder) } - val latestEvent = roomSummaryEntity.latestEvent?.let { - var ev: TimelineEvent? = null - monarchy.doWithRealm { realm -> - ev = timelineEventFactory.create(it, realm) + val latestEvent = if (getLatestEvent) { + roomSummaryEntity.latestEvent?.let { + timelineEventFactory.create(it, it.realm) } - ev + } else { + null } return RoomSummary( roomId = roomSummaryEntity.roomId, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt index 66cc74055c..9c53f5b9ad 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt @@ -34,6 +34,7 @@ import im.vector.matrix.android.internal.database.model.RoomSummaryEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.util.fetchCopied +import im.vector.matrix.android.internal.util.fetchCopyMap import javax.inject.Inject internal class DefaultRoom @Inject constructor(override val roomId: String, @@ -47,19 +48,19 @@ internal class DefaultRoom @Inject constructor(override val roomId: String, private val relationService: RelationService, private val roomMembersService: MembershipService ) : Room, - TimelineService by timelineService, - SendService by sendService, - StateService by stateService, - ReadService by readService, - RelationService by relationService, - MembershipService by roomMembersService { + TimelineService by timelineService, + SendService by sendService, + StateService by stateService, + ReadService by readService, + RelationService by relationService, + MembershipService by roomMembersService { - override val liveRoomSummary: LiveData by lazy { + override fun liveRoomSummary(fetchLastEvent: Boolean): LiveData { val liveRealmData = RealmLiveData(monarchy.realmConfiguration) { realm -> RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) } - Transformations.map(liveRealmData) { results -> - val roomSummaries = results.map { roomSummaryMapper.map(it) } + return Transformations.map(liveRealmData) { results -> + val roomSummaries = results.map { roomSummaryMapper.map(it, fetchLastEvent) } if (roomSummaries.isEmpty()) { // Create a dummy RoomSummary to avoid Crash during Sign Out or clear cache @@ -70,11 +71,12 @@ internal class DefaultRoom @Inject constructor(override val roomId: String, } } - override val roomSummary: RoomSummary? - get() { - var sum: RoomSummaryEntity? = monarchy.fetchCopied { RoomSummaryEntity.where(it, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME).findFirst() } - return sum?.let { roomSummaryMapper.map(it) } - } + override fun roomSummary(fetchLastEvent: Boolean): RoomSummary? { + return monarchy.fetchAllMappedSync( + { realm -> RoomSummaryEntity.where(realm).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) }, + { roomSummaryMapper.map(it, fetchLastEvent) } + ).firstOrNull() + } override fun isEncrypted(): Boolean { return cryptoService.isRoomEncrypted(roomId) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt index 2c0f1ce90c..d40184a0a7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt @@ -52,10 +52,10 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona return roomFactory.create(roomId) } - override fun liveRoomSummaries(): LiveData> { + override fun liveRoomSummaries(fetchLastEvents: Boolean): LiveData> { return monarchy.findAllMappedWithChanges( { realm -> RoomSummaryEntity.where(realm).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) }, - { roomSummaryMapper.map(it) } + { roomSummaryMapper.map(it, fetchLastEvents) } ) } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineEventFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineEventFactory.kt index e9a1090249..aeb35e10cf 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineEventFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineEventFactory.kt @@ -80,7 +80,7 @@ internal class SimpleTimelineEventFactory @Inject constructor(private val roomMe val result = cryptoService.decryptEvent(event, UUID.randomUUID().toString()) event.setClearData(result) } catch (failure: Throwable) { - Timber.e(failure, "Encrypted event: decryption failed") + Timber.e("Encrypted event: decryption failed") if (failure is MXDecryptionException) { event.setCryptoError(failure.cryptoError) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeActivityViewModel.kt index 36d5725561..d3b95f2695 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeActivityViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeActivityViewModel.kt @@ -73,7 +73,7 @@ class HomeActivityViewModel @AssistedInject constructor(@Assisted initialState: private fun observeRoomAndGroup() { Observable .combineLatest, Option, List>( - session.rx().liveRoomSummaries().throttleLast(300, TimeUnit.MILLISECONDS), + session.rx().liveRoomSummaries(fetchLastEvents = true).throttleLast(300, TimeUnit.MILLISECONDS), selectedGroupStore.observe(), BiFunction { rooms, selectedGroupOption -> val selectedGroup = selectedGroupOption.orNull() diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt index 61cea3ccd5..60428713c9 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt @@ -498,7 +498,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro } private fun observeRoomSummary() { - room.rx().liveRoomSummary() + room.rx().liveRoomSummary(false) .execute { async -> copy( asyncRoomSummary = async, diff --git a/vector/src/main/java/im/vector/riotx/features/notifications/NotifiableEventResolver.kt b/vector/src/main/java/im/vector/riotx/features/notifications/NotifiableEventResolver.kt index 2ec916526c..2ab3c03005 100644 --- a/vector/src/main/java/im/vector/riotx/features/notifications/NotifiableEventResolver.kt +++ b/vector/src/main/java/im/vector/riotx/features/notifications/NotifiableEventResolver.kt @@ -117,7 +117,7 @@ class NotifiableEventResolver @Inject constructor(private val stringProvider: St val body = event.annotations?.editSummary?.aggregatedContent?.toModel()?.body ?: event.root.getClearContent().toModel()?.body ?: stringProvider.getString(R.string.notification_unknown_new_event) - val roomName = room.roomSummary?.displayName ?: "" + val roomName = room.roomSummary()?.displayName ?: "" val senderDisplayName = event.senderName ?: event.root.senderId val notifiableEvent = NotifiableMessageEvent( @@ -129,7 +129,7 @@ class NotifiableEventResolver @Inject constructor(private val stringProvider: St body = body, roomId = event.root.roomId!!, roomName = roomName, - roomIsDirect = room.roomSummary?.isDirect ?: false) + roomIsDirect = room.roomSummary()?.isDirect ?: false) notifiableEvent.matrixID = session.sessionParams.credentials.userId notifiableEvent.soundName = null @@ -137,7 +137,7 @@ class NotifiableEventResolver @Inject constructor(private val stringProvider: St // Get the avatars URL // TODO They will be not displayed the first time (known limitation) notifiableEvent.roomAvatarPath = session.contentUrlResolver() - .resolveThumbnail(room.roomSummary?.avatarUrl, + .resolveThumbnail(room.roomSummary()?.avatarUrl, 250, 250, ContentUrlResolver.ThumbnailMethod.SCALE) diff --git a/vector/src/main/java/im/vector/riotx/features/notifications/NotificationBroadcastReceiver.kt b/vector/src/main/java/im/vector/riotx/features/notifications/NotificationBroadcastReceiver.kt index 791072a27b..aff7160b6b 100644 --- a/vector/src/main/java/im/vector/riotx/features/notifications/NotificationBroadcastReceiver.kt +++ b/vector/src/main/java/im/vector/riotx/features/notifications/NotificationBroadcastReceiver.kt @@ -100,8 +100,8 @@ class NotificationBroadcastReceiver : BroadcastReceiver() { session.sessionParams.credentials.userId, message, room.roomId, - room.roomSummary?.displayName ?: room.roomId, - room.roomSummary?.isDirect == true + room.roomSummary()?.displayName ?: room.roomId, + room.roomSummary()?.isDirect == true ) notifiableMessageEvent.outGoingMessage = true diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryViewModel.kt index b34618e240..f7d6c2fb06 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryViewModel.kt @@ -86,7 +86,7 @@ class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState: private fun observeJoinedRooms() { session .rx() - .liveRoomSummaries() + .liveRoomSummaries(fetchLastEvents = false) .subscribe { list -> val joinedRoomIds = list // Keep only joined room diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewViewModel.kt index bf5fa74321..e91b4b0ff6 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewViewModel.kt @@ -54,7 +54,7 @@ class RoomPreviewViewModel @AssistedInject constructor(@Assisted initialState: R private fun observeJoinedRooms() { session .rx() - .liveRoomSummaries() + .liveRoomSummaries(fetchLastEvents = false) .subscribe { list -> withState { state -> val isRoomJoined = list From 9adeab6bae1ed24c81aee1ef67fa07f891db5ad7 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 2 Jul 2019 23:06:40 +0200 Subject: [PATCH 6/6] Perf: revert constraintLayout version as it breaks at the moment --- vector/build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vector/build.gradle b/vector/build.gradle index ffb537153e..e7456c8a71 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -157,7 +157,8 @@ dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" implementation 'androidx.appcompat:appcompat:1.1.0-beta01' - implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2' + //Do not use beta2 at the moment, as it breaks things + implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1' implementation 'androidx.core:core-ktx:1.0.2' implementation 'com.jakewharton.threetenabp:threetenabp:1.1.1'