diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/InitialSyncProgressService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/InitialSyncProgressService.kt new file mode 100644 index 0000000000..3bb567ae00 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/InitialSyncProgressService.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package im.vector.matrix.android.api.session + +import androidx.annotation.StringRes +import androidx.lifecycle.LiveData + +interface InitialSyncProgressService { + + fun getLiveStatus() : LiveData + + data class Status( + @StringRes val statusText: Int?, + val percentProgress: Int = 0 + ) +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt index 3621c6ad21..08e706c3e4 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt @@ -49,14 +49,15 @@ interface Session : FilterService, FileService, PushRuleService, - PushersService { + PushersService, + InitialSyncProgressService { /** * The params associated to the session */ val sessionParams: SessionParams - val myUserId : String + val myUserId: String get() = sessionParams.credentials.userId diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultInitialSyncProgressService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultInitialSyncProgressService.kt new file mode 100644 index 0000000000..cefdcc7290 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultInitialSyncProgressService.kt @@ -0,0 +1,128 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package im.vector.matrix.android.internal.session + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import im.vector.matrix.android.api.session.InitialSyncProgressService +import timber.log.Timber +import javax.inject.Inject + + +@SessionScope +class DefaultInitialSyncProgressService @Inject constructor() : InitialSyncProgressService { + + var status = MutableLiveData() + + var rootTask: TaskInfo? = null + + override fun getLiveStatus(): LiveData { + return status + } + + + fun startTask(nameRes: Int, totalProgress: Int, parentWeight: Float = 1f) { + if (rootTask == null) { + rootTask = TaskInfo(nameRes, totalProgress) + } else { + val currentLeaf = rootTask!!.leaf() + val newTask = TaskInfo(nameRes, totalProgress) + newTask.parent = currentLeaf + newTask.offset = currentLeaf.currentProgress + currentLeaf.child = newTask + newTask.parentWeight = parentWeight + } + reportProgress(0) + } + + fun reportProgress(progress: Int) { + rootTask?.leaf()?.incrementProgress(progress) + } + + fun endTask(nameRes: Int) { + val endedTask = rootTask?.leaf() + if (endedTask?.nameRes == nameRes) { + //close it + val parent = endedTask.parent + parent?.child = null + parent?.incrementProgress(endedTask.offset + (endedTask.totalProgress * endedTask.parentWeight).toInt()) + } + if (endedTask?.parent == null) { + status.postValue(null) + } + } + + fun endAll() { + rootTask = null + status.postValue(null) + } + + + inner class TaskInfo(var nameRes: Int, + var totalProgress: Int) { + var parent: TaskInfo? = null + var child: TaskInfo? = null + var parentWeight: Float = 1f + var currentProgress: Int = 0 + var offset: Int = 0 + + fun leaf(): TaskInfo { + var last = this + while (last.child != null) { + last = last.child!! + } + return last + } + + fun incrementProgress(progress: Int) { + currentProgress = progress +// val newProgress = Math.min(currentProgress + progress, totalProgress) + parent?.let { + val parentProgress = (currentProgress * parentWeight).toInt() + it.incrementProgress(offset + parentProgress) + } + if (parent == null) { + Timber.e("--- ${leaf().nameRes}: ${currentProgress}") + status.postValue( + InitialSyncProgressService.Status(leaf().nameRes, currentProgress) + ) + } + } + } + +} + +inline fun reportSubtask(reporter: DefaultInitialSyncProgressService?, nameRes: Int, totalProgress: Int, parentWeight: Float = 1f, block: () -> T): T { + reporter?.startTask(nameRes, totalProgress, parentWeight) + return block().also { + reporter?.endTask(nameRes) + } +} + + +inline fun Map.mapWithProgress(reporter: DefaultInitialSyncProgressService?, taskId: Int, weight: Float, transform: (Map.Entry) -> R): List { + val total = count() + var current = 0 + reporter?.startTask(taskId, 100, weight) + return this.map { + reporter?.reportProgress((current / total.toFloat() * 100).toInt()) + current++ + transform.invoke(it) + }.also { + reporter?.endTask(taskId) + } +} + diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt index 72fdadfc1e..1e2aec849b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt @@ -24,6 +24,7 @@ import androidx.work.WorkManager import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.auth.data.SessionParams import im.vector.matrix.android.api.pushrules.PushRuleService +import im.vector.matrix.android.api.session.InitialSyncProgressService import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.cache.CacheService import im.vector.matrix.android.api.session.content.ContentUploadStateTracker @@ -64,7 +65,8 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se private val fileService: FileService, private val syncThread: SyncThread, private val contentUrlResolver: ContentUrlResolver, - private val contentUploadProgressTracker: ContentUploadStateTracker) + private val contentUploadProgressTracker: ContentUploadStateTracker, + private val initialSyncProgressService: InitialSyncProgressService) : Session, RoomService by roomService, RoomDirectoryService by roomDirectoryService, @@ -74,9 +76,10 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se CacheService by cacheService, SignOutService by signOutService, FilterService by filterService, - FileService by fileService, PushRuleService by pushRuleService, - PushersService by pushersService { + PushersService by pushersService, + FileService by fileService, + InitialSyncProgressService by initialSyncProgressService { private var isOpen = false diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt index fc23b78037..1738ceddcd 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt @@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.session import dagger.BindsInstance import dagger.Component import im.vector.matrix.android.api.auth.data.SessionParams +import im.vector.matrix.android.api.session.InitialSyncProgressService import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.internal.crypto.CryptoModule import im.vector.matrix.android.internal.di.MatrixComponent diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt index 8f580da11e..d1673bfef3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt @@ -25,6 +25,7 @@ import dagger.multibindings.IntoSet import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig import im.vector.matrix.android.api.auth.data.SessionParams +import im.vector.matrix.android.api.session.InitialSyncProgressService import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.internal.database.LiveEntityObserver import im.vector.matrix.android.internal.database.configureEncryption @@ -132,4 +133,7 @@ internal abstract class SessionModule { @IntoSet abstract fun bindUserEntityUpdater(groupSummaryUpdater: UserEntityUpdater): LiveEntityObserver + @Binds + abstract fun bindInitialSyncProgressService(initialSyncProgressService: DefaultInitialSyncProgressService): InitialSyncProgressService + } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt index a9416a703a..cb102d5d41 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/CryptoSyncHandler.kt @@ -26,6 +26,8 @@ import im.vector.matrix.android.internal.crypto.CryptoManager import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificationService +import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.sync.model.SyncResponse import im.vector.matrix.android.internal.session.sync.model.ToDeviceSyncResponse import timber.log.Timber @@ -35,8 +37,10 @@ import javax.inject.Inject internal class CryptoSyncHandler @Inject constructor(private val cryptoManager: CryptoManager, private val sasVerificationService: DefaultSasVerificationService) { - fun handleToDevice(toDevice: ToDeviceSyncResponse) { - toDevice.events?.forEach { event -> + fun handleToDevice(toDevice: ToDeviceSyncResponse, initialSyncProgressService: DefaultInitialSyncProgressService? = null) { + val total = toDevice.events?.size ?: 0 + toDevice.events?.forEachIndexed { index, event -> + initialSyncProgressService?.reportProgress(((index / total.toFloat()) * 100).toInt()) // Decrypt event if necessary decryptEvent(event, null) if (TextUtils.equals(event.getClearType(), EventType.MESSAGE) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/GroupSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/GroupSyncHandler.kt index d7b8328c7d..29b119dd15 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/GroupSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/GroupSyncHandler.kt @@ -17,10 +17,12 @@ package im.vector.matrix.android.internal.session.sync import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.R import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.internal.database.model.GroupEntity import im.vector.matrix.android.internal.database.query.where -import im.vector.matrix.android.internal.session.SessionScope +import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService +import im.vector.matrix.android.internal.session.mapWithProgress import im.vector.matrix.android.internal.session.sync.model.GroupsSyncResponse import im.vector.matrix.android.internal.session.sync.model.InvitedGroupSync import io.realm.Realm @@ -34,21 +36,33 @@ internal class GroupSyncHandler @Inject constructor(private val monarchy: Monarc data class LEFT(val data: Map) : HandlingStrategy() } - fun handle(roomsSyncResponse: GroupsSyncResponse) { + fun handle(roomsSyncResponse: GroupsSyncResponse, reporter: DefaultInitialSyncProgressService? = null) { monarchy.runTransactionSync { realm -> - handleGroupSync(realm, GroupSyncHandler.HandlingStrategy.JOINED(roomsSyncResponse.join)) - handleGroupSync(realm, GroupSyncHandler.HandlingStrategy.INVITED(roomsSyncResponse.invite)) - handleGroupSync(realm, GroupSyncHandler.HandlingStrategy.LEFT(roomsSyncResponse.leave)) + handleGroupSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join), reporter) + handleGroupSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite), reporter) + handleGroupSync(realm, HandlingStrategy.LEFT(roomsSyncResponse.leave), reporter) } } // PRIVATE METHODS ***************************************************************************** - private fun handleGroupSync(realm: Realm, handlingStrategy: HandlingStrategy) { + private fun handleGroupSync(realm: Realm, handlingStrategy: HandlingStrategy, reporter: DefaultInitialSyncProgressService?) { val groups = when (handlingStrategy) { - is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedGroup(realm, it.key) } - is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedGroup(realm, it.key) } - is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftGroup(realm, it.key) } + is HandlingStrategy.JOINED -> + handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_groups, 0.6f) { + handleJoinedGroup(realm, it.key) + } + + is HandlingStrategy.INVITED -> + handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_groups, 0.3f) { + handleInvitedGroup(realm, it.key) + } + + is HandlingStrategy.LEFT -> + handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_groups, 0.1f) { + handleLeftGroup(realm, it.key) + } + } realm.insertOrUpdate(groups) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt index 3afc57f943..bdf8106461 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt @@ -17,6 +17,7 @@ package im.vector.matrix.android.internal.session.sync import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.R import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.toModel @@ -32,6 +33,8 @@ import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.query.find import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService +import im.vector.matrix.android.internal.session.mapWithProgress import im.vector.matrix.android.internal.session.notification.DefaultPushRuleService import im.vector.matrix.android.internal.session.notification.ProcessEventForPushTask import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater @@ -60,11 +63,11 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch data class LEFT(val data: Map) : HandlingStrategy() } - fun handle(roomsSyncResponse: RoomsSyncResponse) { + fun handle(roomsSyncResponse: RoomsSyncResponse, reporter: DefaultInitialSyncProgressService? = null) { monarchy.runTransactionSync { realm -> - handleRoomSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join)) - handleRoomSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite)) - handleRoomSync(realm, HandlingStrategy.LEFT(roomsSyncResponse.leave)) + handleRoomSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join), reporter) + handleRoomSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite), reporter) + handleRoomSync(realm, HandlingStrategy.LEFT(roomsSyncResponse.leave), reporter) } //handle event for bing rule checks @@ -87,11 +90,23 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch // PRIVATE METHODS ***************************************************************************** - private fun handleRoomSync(realm: Realm, handlingStrategy: HandlingStrategy) { + private fun handleRoomSync(realm: Realm, handlingStrategy: HandlingStrategy, reporter: DefaultInitialSyncProgressService?) { + val rooms = when (handlingStrategy) { - is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) } - is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedRoom(realm, it.key, it.value) } - is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(realm, it.key, it.value) } + is HandlingStrategy.JOINED -> + handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_joined_rooms, 0.6f) { + handleJoinedRoom(realm, it.key, it.value) + } + is HandlingStrategy.INVITED -> + handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_invited_rooms, 0.4f) { + handleInvitedRoom(realm, it.key, it.value) + } + + is HandlingStrategy.LEFT -> { + handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_left_rooms, 0.2f) { + handleLeftRoom(realm, it.key, it.value) + } + } } realm.insertOrUpdate(rooms) } @@ -234,4 +249,4 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch .forEach { roomTagHandler.handle(realm, roomId, it) } } -} \ No newline at end of file +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt index d21b1de3b0..d680a3186a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt @@ -17,7 +17,10 @@ package im.vector.matrix.android.internal.session.sync import arrow.core.Try +import im.vector.matrix.android.R import im.vector.matrix.android.internal.crypto.CryptoManager +import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService +import im.vector.matrix.android.internal.session.reportSubtask import im.vector.matrix.android.internal.session.sync.model.SyncResponse import timber.log.Timber import javax.inject.Inject @@ -27,37 +30,75 @@ internal class SyncResponseHandler @Inject constructor(private val roomSyncHandl private val userAccountDataSyncHandler: UserAccountDataSyncHandler, private val groupSyncHandler: GroupSyncHandler, private val cryptoSyncHandler: CryptoSyncHandler, - private val cryptoManager: CryptoManager) { + private val cryptoManager: CryptoManager, + private val initialSyncProgressService: DefaultInitialSyncProgressService) { fun handleResponse(syncResponse: SyncResponse, fromToken: String?, isCatchingUp: Boolean): Try { return Try { - Timber.v("Start handling sync") val isInitialSync = fromToken == null - if (!cryptoManager.isStarted()) { - Timber.v("Should start cryptoManager") - cryptoManager.start(isInitialSync) + Timber.v("Start handling sync, is InitialSync: $isInitialSync") + val reporter = initialSyncProgressService.takeIf { isInitialSync } + + measureTimeMillis { + if (!cryptoManager.isStarted()) { + Timber.v("Should start cryptoManager") + cryptoManager.start(isInitialSync) + } + }.also { + Timber.v("Finish handling start cryptoManager in $it ms") } val measure = measureTimeMillis { // Handle the to device events before the room ones // to ensure to decrypt them properly - Timber.v("Handle toDevice") - if (syncResponse.toDevice != null) { - cryptoSyncHandler.handleToDevice(syncResponse.toDevice) + measureTimeMillis { + Timber.v("Handle toDevice") + reportSubtask(reporter, R.string.initial_sync_start_importing_account_crypto, 100, 0.1f) { + if (syncResponse.toDevice != null) { + cryptoSyncHandler.handleToDevice(syncResponse.toDevice, reporter) + } + } + }.also { + Timber.v("Finish handling toDevice in $it ms") } - Timber.v("Handle rooms") - if (syncResponse.rooms != null) { - roomSyncHandler.handle(syncResponse.rooms) + + measureTimeMillis { + Timber.v("Handle rooms") + + reportSubtask(reporter, R.string.initial_sync_start_importing_account_rooms, 100, 0.7f) { + if (syncResponse.rooms != null) { + roomSyncHandler.handle(syncResponse.rooms, reporter) + } + } + }.also { + Timber.v("Finish handling rooms in $it ms") } - Timber.v("Handle groups") - if (syncResponse.groups != null) { - groupSyncHandler.handle(syncResponse.groups) + + + measureTimeMillis { + reportSubtask(reporter, R.string.initial_sync_start_importing_account_groups, 100, 0.1f) { + Timber.v("Handle groups") + if (syncResponse.groups != null) { + groupSyncHandler.handle(syncResponse.groups, reporter) + } + } + }.also { + Timber.v("Finish handling groups in $it ms") } - Timber.v("Handle accoundData") - if (syncResponse.accountData != null) { - userAccountDataSyncHandler.handle(syncResponse.accountData) + + measureTimeMillis { + reportSubtask(reporter, R.string.initial_sync_start_importing_account_data, 100, 0.1f) { + Timber.v("Handle accountData") + if (syncResponse.accountData != null) { + userAccountDataSyncHandler.handle(syncResponse.accountData) + } + } + }.also { + Timber.v("Finish handling accountData in $it ms") } + Timber.v("On sync completed") cryptoSyncHandler.onSyncCompleted(syncResponse) + } Timber.v("Finish handling sync in $measure ms") syncResponse diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt index e29f2eeac5..84490404e4 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTask.kt @@ -19,14 +19,18 @@ package im.vector.matrix.android.internal.session.sync import arrow.core.Try import arrow.core.failure import arrow.core.recoverWith +import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.R import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.failure.MatrixError import im.vector.matrix.android.internal.auth.SessionParamsStore import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService import im.vector.matrix.android.internal.session.filter.FilterRepository import im.vector.matrix.android.internal.session.sync.model.SyncResponse import im.vector.matrix.android.internal.task.Task +import im.vector.matrix.android.internal.util.tryTransactionAsync import javax.inject.Inject internal interface SyncTask : Task { @@ -40,7 +44,9 @@ internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI, private val filterRepository: FilterRepository, private val syncResponseHandler: SyncResponseHandler, private val sessionParamsStore: SessionParamsStore, - private val syncTokenStore: SyncTokenStore + private val initialSyncProgressService: DefaultInitialSyncProgressService, + private val syncTokenStore: SyncTokenStore, + private val monarchy: Monarchy ) : SyncTask { @@ -55,6 +61,11 @@ internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI, requestParams["timeout"] = timeout.toString() requestParams["filter"] = filterRepository.getFilter() + val isInitialSync = token == null + if (isInitialSync) { + initialSyncProgressService.endAll() + initialSyncProgressService.startTask(R.string.initial_sync_start_importing_account, 100) + } return executeRequest { apiCall = syncAPI.sync(requestParams) }.recoverWith { throwable -> @@ -67,7 +78,13 @@ internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI, // Transmit the throwable throwable.failure() }.flatMap { syncResponse -> - syncResponseHandler.handleResponse(syncResponse, token, false) + syncResponseHandler.handleResponse(syncResponse, token, false).also { + if (isInitialSync) { + monarchy.tryTransactionAsync { + initialSyncProgressService.endAll() + } + } + } }.map { syncTokenStore.saveToken(it.nextBatch) } diff --git a/matrix-sdk-android/src/main/res/values/strings_RiotX.xml b/matrix-sdk-android/src/main/res/values/strings_RiotX.xml new file mode 100644 index 0000000000..d03dfa79b9 --- /dev/null +++ b/matrix-sdk-android/src/main/res/values/strings_RiotX.xml @@ -0,0 +1,10 @@ + + Initial Sync:\nImporting account… + Initial Sync:\nImporting crypto + Initial Sync:\nImporting Rooms + Initial Sync:\nImporting Joined Rooms + Initial Sync:\nImporting Invited Rooms + Initial Sync:\nImporting Left Rooms + Initial Sync:\nImporting Communities + Initial Sync:\nImporting Account Data + \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeActivity.kt index 21ca495ab9..67d1af4e44 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeActivity.kt @@ -24,6 +24,7 @@ import android.view.MenuItem import androidx.appcompat.app.AlertDialog import androidx.appcompat.widget.Toolbar import androidx.core.view.GravityCompat +import androidx.core.view.isVisible import androidx.drawerlayout.widget.DrawerLayout import androidx.fragment.app.FragmentManager import androidx.lifecycle.Observer @@ -45,6 +46,8 @@ import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler import im.vector.riotx.features.workers.signout.SignOutViewModel import im.vector.riotx.push.fcm.FcmHelper import kotlinx.android.synthetic.main.activity_home.* +import kotlinx.android.synthetic.main.merge_overlay_waiting_view.* +import timber.log.Timber import javax.inject.Inject @@ -114,6 +117,28 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable { notificationDrawerManager.clearAllEvents() intent.removeExtra(EXTRA_CLEAR_EXISTING_NOTIFICATION) } + + activeSessionHolder.getSafeActiveSession()?.getLiveStatus()?.observe(this, Observer { sprogress -> + Timber.e("${sprogress?.statusText?.let { getString(it) }} ${sprogress?.percentProgress}") + if (sprogress == null) { + waiting_view.isVisible = false + } else { + waiting_view.setOnClickListener { + //block interactions + } + waiting_view_status_horizontal_progress.apply { + isIndeterminate = false + max = 100 + progress = sprogress.percentProgress + isVisible = true + } + waiting_view_status_text.apply { + text = sprogress.statusText?.let { getString(it) } + isVisible = true + } + waiting_view.isVisible = true + } + }) } override fun onNewIntent(intent: Intent?) { diff --git a/vector/src/main/java/im/vector/riotx/features/notifications/NotificationDrawerManager.kt b/vector/src/main/java/im/vector/riotx/features/notifications/NotificationDrawerManager.kt index 158461a926..763aea5e4e 100644 --- a/vector/src/main/java/im/vector/riotx/features/notifications/NotificationDrawerManager.kt +++ b/vector/src/main/java/im/vector/riotx/features/notifications/NotificationDrawerManager.kt @@ -184,7 +184,7 @@ class NotificationDrawerManager @Inject constructor(private val context: Context val session = activeSessionHolder.getActiveSession() val user = session.getUser(session.sessionParams.credentials.userId) - val myUserDisplayName = user?.displayName ?: "" + val myUserDisplayName = user?.displayName ?: session.sessionParams.credentials.userId val myUserAvatarUrl = session.contentUrlResolver().resolveThumbnail(user?.avatarUrl, avatarSize, avatarSize, ContentUrlResolver.ThumbnailMethod.SCALE) synchronized(eventList) { diff --git a/vector/src/main/java/im/vector/riotx/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/riotx/features/rageshake/BugReporter.kt index 7bb75c4ed9..774bdfb9d9 100755 --- a/vector/src/main/java/im/vector/riotx/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/riotx/features/rageshake/BugReporter.kt @@ -51,7 +51,7 @@ import javax.inject.Singleton * BugReporter creates and sends the bug reports. */ @Singleton -class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSessionHolder){ +class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSessionHolder) { var inMultiWindowMode = false companion object { diff --git a/vector/src/main/res/layout/activity.xml b/vector/src/main/res/layout/activity.xml index 9a5c32e4f2..df0cd3fbea 100644 --- a/vector/src/main/res/layout/activity.xml +++ b/vector/src/main/res/layout/activity.xml @@ -22,66 +22,6 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/toolbar" /> - - - - - - - - - - - - - - - - - + diff --git a/vector/src/main/res/layout/activity_home.xml b/vector/src/main/res/layout/activity_home.xml index 599b7d4cfb..c6f74147d5 100644 --- a/vector/src/main/res/layout/activity_home.xml +++ b/vector/src/main/res/layout/activity_home.xml @@ -15,6 +15,8 @@ android:id="@+id/homeDetailFragmentContainer" android:layout_width="match_parent" android:layout_height="match_parent" /> + + @@ -24,4 +26,5 @@ android:layout_height="match_parent" android:layout_gravity="start" /> + \ No newline at end of file diff --git a/vector/src/main/res/layout/merge_overlay_waiting_view.xml b/vector/src/main/res/layout/merge_overlay_waiting_view.xml new file mode 100644 index 0000000000..8f09ed0988 --- /dev/null +++ b/vector/src/main/res/layout/merge_overlay_waiting_view.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file