Remove string usage from SDK - step 2 - InitSyncStep

This commit is contained in:
Benoit Marty 2021-03-03 12:43:05 +01:00
parent c42b42cb61
commit e2e7516a99
12 changed files with 115 additions and 41 deletions

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2021 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 org.matrix.android.sdk.api.session.initsync
enum class InitSyncStep {
ServerComputing,
Downloading,
ImportingAccount,
ImportingAccountCrypto,
ImportingAccountRoom,
ImportingAccountGroups,
ImportingAccountData,
ImportingAccountJoinedRooms,
ImportingAccountInvitedRooms,
ImportingAccountLeftRooms
}

View file

@ -15,7 +15,6 @@
*/
package org.matrix.android.sdk.api.session.initsync
import androidx.annotation.StringRes
import androidx.lifecycle.LiveData
interface InitialSyncProgressService {
@ -25,7 +24,7 @@ interface InitialSyncProgressService {
sealed class Status {
object Idle : Status()
data class Progressing(
@StringRes val statusText: Int,
val initSyncStep: InitSyncStep,
val percentProgress: Int = 0
) : Status()
}

View file

@ -15,9 +15,9 @@
*/
package org.matrix.android.sdk.internal.session.initsync
import androidx.annotation.StringRes
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import org.matrix.android.sdk.api.session.initsync.InitSyncStep
import org.matrix.android.sdk.api.session.initsync.InitialSyncProgressService
import org.matrix.android.sdk.internal.session.SessionScope
import javax.inject.Inject
@ -38,22 +38,22 @@ internal class DefaultInitialSyncProgressService @Inject constructor()
/**
* Create a rootTask
*/
fun startRoot(@StringRes nameRes: Int,
fun startRoot(initSyncStep: InitSyncStep,
totalProgress: Int) {
endAll()
rootTask = TaskInfo(nameRes, totalProgress, null, 1F)
rootTask = TaskInfo(initSyncStep, totalProgress, null, 1F)
reportProgress(0F)
}
/**
* Add a child to the leaf
*/
override fun startTask(@StringRes nameRes: Int,
override fun startTask(initSyncStep: InitSyncStep,
totalProgress: Int,
parentWeight: Float) {
val currentLeaf = rootTask?.leaf() ?: return
currentLeaf.child = TaskInfo(
nameRes = nameRes,
initSyncStep = initSyncStep,
totalProgress = totalProgress,
parent = currentLeaf,
parentWeight = parentWeight
@ -67,7 +67,7 @@ internal class DefaultInitialSyncProgressService @Inject constructor()
// Update the progress of the leaf and all its parents
leaf.setProgress(progress)
// Then update the live data using leaf wording and root progress
status.postValue(InitialSyncProgressService.Status.Progressing(leaf.nameRes, root.currentProgress.toInt()))
status.postValue(InitialSyncProgressService.Status.Progressing(leaf.initSyncStep, root.currentProgress.toInt()))
}
}
}

View file

@ -16,25 +16,25 @@
package org.matrix.android.sdk.internal.session.initsync
import androidx.annotation.StringRes
import org.matrix.android.sdk.api.session.initsync.InitSyncStep
internal inline fun <T> reportSubtask(reporter: ProgressReporter?,
@StringRes nameRes: Int,
initSyncStep: InitSyncStep,
totalProgress: Int,
parentWeight: Float,
block: () -> T): T {
reporter?.startTask(nameRes, totalProgress, parentWeight)
reporter?.startTask(initSyncStep, totalProgress, parentWeight)
return block().also {
reporter?.endTask()
}
}
internal inline fun <K, V, R> Map<out K, V>.mapWithProgress(reporter: ProgressReporter?,
@StringRes nameRes: Int,
initSyncStep: InitSyncStep,
parentWeight: Float,
transform: (Map.Entry<K, V>) -> R): List<R> {
var current = 0F
reporter?.startTask(nameRes, count() + 1, parentWeight)
reporter?.startTask(initSyncStep, count() + 1, parentWeight)
return map {
reporter?.reportProgress(current)
current++

View file

@ -16,10 +16,10 @@
package org.matrix.android.sdk.internal.session.initsync
import androidx.annotation.StringRes
import org.matrix.android.sdk.api.session.initsync.InitSyncStep
internal interface ProgressReporter {
fun startTask(@StringRes nameRes: Int,
fun startTask(initSyncStep: InitSyncStep,
totalProgress: Int,
parentWeight: Float)

View file

@ -16,10 +16,10 @@
package org.matrix.android.sdk.internal.session.initsync
import androidx.annotation.StringRes
import org.matrix.android.sdk.api.session.initsync.InitSyncStep
import timber.log.Timber
internal class TaskInfo(@StringRes val nameRes: Int,
internal class TaskInfo(val initSyncStep: InitSyncStep,
val totalProgress: Int,
val parent: TaskInfo?,
val parentWeight: Float) {

View file

@ -17,7 +17,7 @@
package org.matrix.android.sdk.internal.session.sync
import io.realm.Realm
import org.matrix.android.sdk.R
import org.matrix.android.sdk.api.session.initsync.InitSyncStep
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.internal.database.model.GroupEntity
import org.matrix.android.sdk.internal.database.model.GroupSummaryEntity
@ -50,17 +50,17 @@ internal class GroupSyncHandler @Inject constructor() {
private fun handleGroupSync(realm: Realm, handlingStrategy: HandlingStrategy, reporter: ProgressReporter?) {
val groups = when (handlingStrategy) {
is HandlingStrategy.JOINED ->
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_groups, 0.6f) {
handlingStrategy.data.mapWithProgress(reporter, InitSyncStep.ImportingAccountGroups, 0.6f) {
handleJoinedGroup(realm, it.key)
}
is HandlingStrategy.INVITED ->
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_groups, 0.3f) {
handlingStrategy.data.mapWithProgress(reporter, InitSyncStep.ImportingAccountGroups, 0.3f) {
handleInvitedGroup(realm, it.key)
}
is HandlingStrategy.LEFT ->
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_groups, 0.1f) {
handlingStrategy.data.mapWithProgress(reporter, InitSyncStep.ImportingAccountGroups, 0.1f) {
handleLeftGroup(realm, it.key)
}
}

View file

@ -18,11 +18,11 @@ package org.matrix.android.sdk.internal.session.sync
import io.realm.Realm
import io.realm.kotlin.createObject
import org.matrix.android.sdk.R
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.initsync.InitSyncStep
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
import org.matrix.android.sdk.api.session.room.model.tag.RoomTagContent
@ -112,18 +112,18 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
// Rooms are already inserted, return an empty list
emptyList()
} else {
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_joined_rooms, 0.6f) {
handlingStrategy.data.mapWithProgress(reporter, InitSyncStep.ImportingAccountJoinedRooms, 0.6f) {
handleJoinedRoom(realm, it.key, it.value.roomSync, insertType, syncLocalTimeStampMillis)
}
}
}
is HandlingStrategy.INVITED ->
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_invited_rooms, 0.1f) {
handlingStrategy.data.mapWithProgress(reporter, InitSyncStep.ImportingAccountInvitedRooms, 0.1f) {
handleInvitedRoom(realm, it.key, it.value, insertType, syncLocalTimeStampMillis)
}
is HandlingStrategy.LEFT -> {
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_left_rooms, 0.3f) {
handlingStrategy.data.mapWithProgress(reporter, InitSyncStep.ImportingAccountLeftRooms, 0.3f) {
handleLeftRoom(realm, it.key, it.value, insertType, syncLocalTimeStampMillis)
}
}
@ -141,7 +141,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
val numberOfChunks = ceil(listSize / maxSize.toDouble()).toInt()
if (numberOfChunks > 1) {
reportSubtask(reporter, R.string.initial_sync_start_importing_account_joined_rooms, numberOfChunks, 0.6f) {
reportSubtask(reporter, InitSyncStep.ImportingAccountJoinedRooms, numberOfChunks, 0.6f) {
val chunkSize = listSize / numberOfChunks
Timber.v("INIT_SYNC $listSize rooms to insert, split into $numberOfChunks sublists of $chunkSize items")
// I cannot find a better way to chunk a map, so chunk the keys and then create new maps
@ -165,7 +165,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
}
} else {
// No need to split
val rooms = handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_joined_rooms, 0.6f) {
val rooms = handlingStrategy.data.mapWithProgress(reporter, InitSyncStep.ImportingAccountJoinedRooms, 0.6f) {
handleJoinedRoom(realm, it.key, it.value.roomSync, insertType, syncLocalTimeStampMillis)
}
realm.insertOrUpdate(rooms)

View file

@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.session.sync
import androidx.work.ExistingPeriodicWorkPolicy
import com.zhuinden.monarchy.Monarchy
import org.matrix.android.sdk.R
import org.matrix.android.sdk.api.pushrules.PushRuleService
import org.matrix.android.sdk.api.pushrules.RuleScope
import org.matrix.android.sdk.api.session.initsync.InitSyncStep
import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.di.SessionId
@ -73,7 +73,7 @@ internal class SyncResponseHandler @Inject constructor(@SessionDatabase private
// to ensure to decrypt them properly
measureTimeMillis {
Timber.v("Handle toDevice")
reportSubtask(reporter, R.string.initial_sync_start_importing_account_crypto, 100, 0.1f) {
reportSubtask(reporter, InitSyncStep.ImportingAccountCrypto, 100, 0.1f) {
if (syncResponse.toDevice != null) {
cryptoSyncHandler.handleToDevice(syncResponse.toDevice, reporter)
}
@ -85,7 +85,7 @@ internal class SyncResponseHandler @Inject constructor(@SessionDatabase private
monarchy.awaitTransaction { realm ->
measureTimeMillis {
Timber.v("Handle rooms")
reportSubtask(reporter, R.string.initial_sync_start_importing_account_rooms, 1, 0.7f) {
reportSubtask(reporter, InitSyncStep.ImportingAccountRoom, 1, 0.7f) {
if (syncResponse.rooms != null) {
roomSyncHandler.handle(realm, syncResponse.rooms, isInitialSync, reporter)
}
@ -95,7 +95,7 @@ internal class SyncResponseHandler @Inject constructor(@SessionDatabase private
}
measureTimeMillis {
reportSubtask(reporter, R.string.initial_sync_start_importing_account_groups, 1, 0.1f) {
reportSubtask(reporter, InitSyncStep.ImportingAccountGroups, 1, 0.1f) {
Timber.v("Handle groups")
if (syncResponse.groups != null) {
groupSyncHandler.handle(realm, syncResponse.groups, reporter)
@ -106,7 +106,7 @@ internal class SyncResponseHandler @Inject constructor(@SessionDatabase private
}
measureTimeMillis {
reportSubtask(reporter, R.string.initial_sync_start_importing_account_data, 1, 0.1f) {
reportSubtask(reporter, InitSyncStep.ImportingAccountData, 1, 0.1f) {
Timber.v("Handle accountData")
userAccountDataSyncHandler.handle(realm, syncResponse.accountData)
}

View file

@ -17,7 +17,7 @@
package org.matrix.android.sdk.internal.session.sync
import okhttp3.ResponseBody
import org.matrix.android.sdk.R
import org.matrix.android.sdk.api.session.initsync.InitSyncStep
import org.matrix.android.sdk.internal.di.SessionFilesDirectory
import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
@ -90,7 +90,7 @@ internal class DefaultSyncTask @Inject constructor(
if (isInitialSync) {
// We might want to get the user information in parallel too
userStore.createOrUpdate(userId)
initialSyncProgressService.startRoot(R.string.initial_sync_start_importing_account, 100)
initialSyncProgressService.startRoot(InitSyncStep.ImportingAccount, 100)
}
// Maybe refresh the home server capabilities data we know
getHomeServerCapabilitiesTask.execute(GetHomeServerCapabilitiesTask.Params(forceRefresh = false))
@ -137,20 +137,20 @@ internal class DefaultSyncTask @Inject constructor(
if (workingFile.exists() && status >= InitialSyncStatus.STEP_DOWNLOADED) {
// Go directly to the parse step
Timber.v("INIT_SYNC file is already here")
reportSubtask(initialSyncProgressService, R.string.initial_sync_start_downloading, 1, 0.3f) {
reportSubtask(initialSyncProgressService, InitSyncStep.Downloading, 1, 0.3f) {
// Empty task
}
} else {
initialSyncStatusRepository.setStep(InitialSyncStatus.STEP_DOWNLOADING)
val syncResponse = logDuration("INIT_SYNC Perform server request") {
reportSubtask(initialSyncProgressService, R.string.initial_sync_start_server_computing, 1, 0.2f) {
reportSubtask(initialSyncProgressService, InitSyncStep.ServerComputing, 1, 0.2f) {
getSyncResponse(requestParams, MAX_NUMBER_OF_RETRY_AFTER_TIMEOUT)
}
}
if (syncResponse.isSuccessful) {
logDuration("INIT_SYNC Download and save to file") {
reportSubtask(initialSyncProgressService, R.string.initial_sync_start_downloading, 1, 0.1f) {
reportSubtask(initialSyncProgressService, InitSyncStep.Downloading, 1, 0.1f) {
syncResponse.body()?.byteStream()?.use { inputStream ->
workingFile.outputStream().use { outputStream ->
inputStream.copyTo(outputStream)
@ -164,7 +164,7 @@ internal class DefaultSyncTask @Inject constructor(
}
initialSyncStatusRepository.setStep(InitialSyncStatus.STEP_DOWNLOADED)
}
reportSubtask(initialSyncProgressService, R.string.initial_sync_start_importing_account, 1, 0.7F) {
reportSubtask(initialSyncProgressService, InitSyncStep.ImportingAccount, 1, 0.7F) {
handleSyncFile(workingFile, initSyncStrategy)
}

View file

@ -99,6 +99,7 @@ class HomeActivity :
@Inject lateinit var unknownDeviceViewModelFactory: UnknownDeviceDetectorSharedViewModel.Factory
@Inject lateinit var permalinkHandler: PermalinkHandler
@Inject lateinit var avatarRenderer: AvatarRenderer
@Inject lateinit var initSyncStepFormatter: InitSyncStepFormatter
private val drawerListener = object : DrawerLayout.SimpleDrawerListener() {
override fun onDrawerStateChanged(newState: Int) {
@ -208,11 +209,12 @@ class HomeActivity :
private fun renderState(state: HomeActivityViewState) {
when (val status = state.initialSyncProgressServiceStatus) {
is InitialSyncProgressService.Status.Idle -> {
is InitialSyncProgressService.Status.Idle -> {
views.waitingView.root.isVisible = false
}
is InitialSyncProgressService.Status.Progressing -> {
Timber.v("${getString(status.statusText)} ${status.percentProgress}")
val initSyncStepStr = initSyncStepFormatter.format(status.initSyncStep)
Timber.v("$initSyncStepStr ${status.percentProgress}")
views.waitingView.root.setOnClickListener {
// block interactions
}
@ -223,7 +225,7 @@ class HomeActivity :
isVisible = true
}
views.waitingView.waitingStatusText.apply {
text = getString(status.statusText)
text = initSyncStepStr
isVisible = true
}
views.waitingView.root.isVisible = true

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2021 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.app.features.home
import im.vector.app.R
import im.vector.app.core.resources.StringProvider
import org.matrix.android.sdk.api.session.initsync.InitSyncStep
import javax.inject.Inject
class InitSyncStepFormatter @Inject constructor(
private val stringProvider: StringProvider
) {
fun format(initSyncStep: InitSyncStep): String {
return stringProvider.getString(
when (initSyncStep) {
InitSyncStep.ServerComputing -> R.string.initial_sync_start_server_computing
InitSyncStep.Downloading -> R.string.initial_sync_start_downloading
InitSyncStep.ImportingAccount -> R.string.initial_sync_start_importing_account
InitSyncStep.ImportingAccountCrypto -> R.string.initial_sync_start_importing_account_crypto
InitSyncStep.ImportingAccountRoom -> R.string.initial_sync_start_importing_account_rooms
InitSyncStep.ImportingAccountGroups -> R.string.initial_sync_start_importing_account_groups
InitSyncStep.ImportingAccountData -> R.string.initial_sync_start_importing_account_data
InitSyncStep.ImportingAccountJoinedRooms -> R.string.initial_sync_start_importing_account_joined_rooms
InitSyncStep.ImportingAccountInvitedRooms -> R.string.initial_sync_start_importing_account_invited_rooms
InitSyncStep.ImportingAccountLeftRooms -> R.string.initial_sync_start_importing_account_left_rooms
}
)
}
}