forked from GitHub-Mirror/riotX-android
143 lines
4.6 KiB
Kotlin
143 lines
4.6 KiB
Kotlin
/*
|
|
* 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.annotation.StringRes
|
|
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 {
|
|
|
|
private var status = MutableLiveData<InitialSyncProgressService.Status>()
|
|
|
|
private var rootTask: TaskInfo? = null
|
|
|
|
override fun getInitialSyncProgressStatus(): LiveData<InitialSyncProgressService.Status?> {
|
|
return status
|
|
}
|
|
|
|
fun startTask(@StringRes nameRes: Int, totalProgress: Int, parentWeight: Float = 1f) {
|
|
// Create a rootTask, or add a child to the leaf
|
|
if (rootTask == null) {
|
|
rootTask = TaskInfo(nameRes, totalProgress)
|
|
} else {
|
|
val currentLeaf = rootTask!!.leaf()
|
|
|
|
val newTask = TaskInfo(nameRes,
|
|
totalProgress,
|
|
currentLeaf,
|
|
parentWeight)
|
|
|
|
currentLeaf.child = newTask
|
|
}
|
|
reportProgress(0)
|
|
}
|
|
|
|
fun reportProgress(progress: Int) {
|
|
rootTask?.leaf()?.setProgress(progress)
|
|
}
|
|
|
|
fun endTask(nameRes: Int) {
|
|
val endedTask = rootTask?.leaf()
|
|
if (endedTask?.nameRes == nameRes) {
|
|
//close it
|
|
val parent = endedTask.parent
|
|
parent?.child = null
|
|
parent?.setProgress(endedTask.offset + (endedTask.totalProgress * endedTask.parentWeight).toInt())
|
|
}
|
|
if (endedTask?.parent == null) {
|
|
status.postValue(null)
|
|
}
|
|
}
|
|
|
|
fun endAll() {
|
|
rootTask = null
|
|
status.postValue(null)
|
|
}
|
|
|
|
|
|
private inner class TaskInfo(@StringRes var nameRes: Int,
|
|
var totalProgress: Int,
|
|
var parent: TaskInfo? = null,
|
|
var parentWeight: Float = 1f,
|
|
var offset: Int = parent?.currentProgress ?: 0) {
|
|
var child: TaskInfo? = null
|
|
var currentProgress: Int = 0
|
|
|
|
/**
|
|
* Get the further child
|
|
*/
|
|
fun leaf(): TaskInfo {
|
|
var last = this
|
|
while (last.child != null) {
|
|
last = last.child!!
|
|
}
|
|
return last
|
|
}
|
|
|
|
/**
|
|
* Set progress of the parent if any (which will post value), or post the value
|
|
*/
|
|
fun setProgress(progress: Int) {
|
|
currentProgress = progress
|
|
// val newProgress = Math.min(currentProgress + progress, totalProgress)
|
|
parent?.let {
|
|
val parentProgress = (currentProgress * parentWeight).toInt()
|
|
it.setProgress(offset + parentProgress)
|
|
} ?: run {
|
|
Timber.e("--- ${leaf().nameRes}: $currentProgress")
|
|
status.postValue(
|
|
InitialSyncProgressService.Status(leaf().nameRes, currentProgress)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
inline fun <T> reportSubtask(reporter: DefaultInitialSyncProgressService?,
|
|
@StringRes nameRes: Int,
|
|
totalProgress: Int,
|
|
parentWeight: Float = 1f,
|
|
block: () -> T): T {
|
|
reporter?.startTask(nameRes, totalProgress, parentWeight)
|
|
return block().also {
|
|
reporter?.endTask(nameRes)
|
|
}
|
|
}
|
|
|
|
|
|
inline fun <K, V, R> Map<out K, V>.mapWithProgress(reporter: DefaultInitialSyncProgressService?,
|
|
taskId: Int,
|
|
weight: Float,
|
|
transform: (Map.Entry<K, V>) -> R): List<R> {
|
|
val total = count().toFloat()
|
|
var current = 0
|
|
reporter?.startTask(taskId, 100, weight)
|
|
return map {
|
|
reporter?.reportProgress((current / total * 100).toInt())
|
|
current++
|
|
transform.invoke(it)
|
|
}.also {
|
|
reporter?.endTask(taskId)
|
|
}
|
|
}
|
|
|