forked from GitHub-Mirror/riotX-android
Merge branch 'feature/sync_ui' into develop
This commit is contained in:
@ -17,6 +17,7 @@
|
||||
package im.vector.matrix.android.api.session
|
||||
|
||||
import androidx.annotation.MainThread
|
||||
import androidx.lifecycle.LiveData
|
||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||
import im.vector.matrix.android.api.session.cache.CacheService
|
||||
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
|
||||
@ -27,6 +28,7 @@ import im.vector.matrix.android.api.session.room.RoomDirectoryService
|
||||
import im.vector.matrix.android.api.session.room.RoomService
|
||||
import im.vector.matrix.android.api.session.signout.SignOutService
|
||||
import im.vector.matrix.android.api.session.sync.FilterService
|
||||
import im.vector.matrix.android.api.session.sync.SyncState
|
||||
import im.vector.matrix.android.api.session.user.UserService
|
||||
|
||||
/**
|
||||
@ -66,6 +68,12 @@ interface Session :
|
||||
@MainThread
|
||||
fun stopSync()
|
||||
|
||||
/**
|
||||
* This method allows to listen the sync state.
|
||||
* @return a [LiveData] of [SyncState].
|
||||
*/
|
||||
fun syncState(): LiveData<SyncState>
|
||||
|
||||
/**
|
||||
* This method allow to close a session. It does stop some services.
|
||||
*/
|
||||
@ -102,6 +110,7 @@ interface Session :
|
||||
* The access token is not valid anymore
|
||||
*/
|
||||
fun onInvalidToken()
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -22,12 +22,6 @@ interface ContentUploadStateTracker {
|
||||
|
||||
fun untrack(key: String, updateListener: UpdateListener)
|
||||
|
||||
fun setFailure(key: String)
|
||||
|
||||
fun setSuccess(key: String)
|
||||
|
||||
fun setProgress(key: String, current: Long, total: Long)
|
||||
|
||||
interface UpdateListener {
|
||||
fun onUpdate(state: State)
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
*
|
||||
* * 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.sync
|
||||
|
||||
sealed class SyncState {
|
||||
object IDLE : SyncState()
|
||||
data class RUNNING(val catchingUp: Boolean) : SyncState()
|
||||
object PAUSED : SyncState()
|
||||
object KILLING : SyncState()
|
||||
object KILLED : SyncState()
|
||||
}
|
@ -46,6 +46,7 @@ import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRooms
|
||||
import im.vector.matrix.android.api.session.room.model.thirdparty.ThirdPartyProtocol
|
||||
import im.vector.matrix.android.api.session.signout.SignOutService
|
||||
import im.vector.matrix.android.api.session.sync.FilterService
|
||||
import im.vector.matrix.android.api.session.sync.SyncState
|
||||
import im.vector.matrix.android.api.session.user.UserService
|
||||
import im.vector.matrix.android.api.session.user.model.User
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
@ -150,6 +151,10 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi
|
||||
isOpen = false
|
||||
}
|
||||
|
||||
override fun syncState(): LiveData<SyncState> {
|
||||
return syncThread.liveState()
|
||||
}
|
||||
|
||||
@MainThread
|
||||
override fun signOut(callback: MatrixCallback<Unit>) {
|
||||
Timber.w("SIGN_OUT: start")
|
||||
|
@ -27,7 +27,11 @@ internal class ContentModule {
|
||||
val definition = module(override = true) {
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
DefaultContentUploadStateTracker() as ContentUploadStateTracker
|
||||
DefaultContentUploadStateTracker()
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
get<DefaultContentUploadStateTracker>() as ContentUploadStateTracker
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
|
@ -40,17 +40,17 @@ internal class DefaultContentUploadStateTracker : ContentUploadStateTracker {
|
||||
}
|
||||
}
|
||||
|
||||
override fun setFailure(key: String) {
|
||||
internal fun setFailure(key: String) {
|
||||
val failure = ContentUploadStateTracker.State.Failure
|
||||
updateState(key, failure)
|
||||
}
|
||||
|
||||
override fun setSuccess(key: String) {
|
||||
internal fun setSuccess(key: String) {
|
||||
val success = ContentUploadStateTracker.State.Success
|
||||
updateState(key, success)
|
||||
}
|
||||
|
||||
override fun setProgress(key: String, current: Long, total: Long) {
|
||||
internal fun setProgress(key: String, current: Long, total: Long) {
|
||||
val progressData = ContentUploadStateTracker.State.ProgressData(current, total)
|
||||
updateState(key, progressData)
|
||||
}
|
||||
|
@ -21,15 +21,10 @@ import androidx.work.CoroutineWorker
|
||||
import androidx.work.WorkerParameters
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.events.model.toContent
|
||||
import im.vector.matrix.android.api.session.events.model.toModel
|
||||
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.MessageFileContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.*
|
||||
import im.vector.matrix.android.internal.di.MatrixKoinComponent
|
||||
import im.vector.matrix.android.internal.network.ProgressRequestBody
|
||||
import im.vector.matrix.android.internal.session.room.send.SendEventWorker
|
||||
@ -43,7 +38,7 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters)
|
||||
: CoroutineWorker(context, params), MatrixKoinComponent {
|
||||
|
||||
private val fileUploader by inject<FileUploader>()
|
||||
private val contentUploadProgressTracker by inject<ContentUploadStateTracker>()
|
||||
private val contentUploadProgressTracker by inject<DefaultContentUploadStateTracker>()
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class Params(
|
||||
|
@ -16,10 +16,13 @@
|
||||
|
||||
package im.vector.matrix.android.internal.session.sync.job
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.squareup.moshi.JsonEncodingException
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.failure.MatrixError
|
||||
import im.vector.matrix.android.api.session.sync.SyncState
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
|
||||
import im.vector.matrix.android.internal.session.sync.SyncTask
|
||||
@ -42,61 +45,52 @@ internal class SyncThread(private val syncTask: SyncTask,
|
||||
private val taskExecutor: TaskExecutor
|
||||
) : Thread(), NetworkConnectivityChecker.Listener, BackgroundDetectionObserver.Listener {
|
||||
|
||||
enum class State {
|
||||
IDLE,
|
||||
RUNNING,
|
||||
PAUSED,
|
||||
KILLING,
|
||||
KILLED
|
||||
}
|
||||
|
||||
private var state: State = State.IDLE
|
||||
private var state: SyncState = SyncState.IDLE
|
||||
private var liveState = MutableLiveData<SyncState>()
|
||||
private val lock = Object()
|
||||
private var nextBatch = syncTokenStore.getLastToken()
|
||||
private var cancelableTask: Cancelable? = null
|
||||
|
||||
fun restart() {
|
||||
synchronized(lock) {
|
||||
if (state != State.PAUSED) {
|
||||
return@synchronized
|
||||
}
|
||||
Timber.v("Resume sync...")
|
||||
init {
|
||||
updateStateTo(SyncState.IDLE)
|
||||
}
|
||||
|
||||
fun restart() = synchronized(lock) {
|
||||
if (state is SyncState.PAUSED) {
|
||||
Timber.v("Resume sync...")
|
||||
// Retrieve the last token, it may have been deleted in case of a clear cache
|
||||
nextBatch = syncTokenStore.getLastToken()
|
||||
|
||||
state = State.RUNNING
|
||||
updateStateTo(SyncState.RUNNING(catchingUp = true))
|
||||
lock.notify()
|
||||
}
|
||||
}
|
||||
|
||||
fun pause() {
|
||||
synchronized(lock) {
|
||||
if (state != State.RUNNING) {
|
||||
return@synchronized
|
||||
}
|
||||
fun pause() = synchronized(lock) {
|
||||
if (state is SyncState.RUNNING) {
|
||||
Timber.v("Pause sync...")
|
||||
state = State.PAUSED
|
||||
updateStateTo(SyncState.PAUSED)
|
||||
}
|
||||
}
|
||||
|
||||
fun kill() {
|
||||
synchronized(lock) {
|
||||
Timber.v("Kill sync...")
|
||||
state = State.KILLING
|
||||
cancelableTask?.cancel()
|
||||
lock.notify()
|
||||
}
|
||||
fun kill() = synchronized(lock) {
|
||||
Timber.v("Kill sync...")
|
||||
updateStateTo(SyncState.KILLING)
|
||||
cancelableTask?.cancel()
|
||||
lock.notify()
|
||||
}
|
||||
|
||||
fun liveState(): LiveData<SyncState> {
|
||||
return liveState
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
Timber.v("Start syncing...")
|
||||
networkConnectivityChecker.register(this)
|
||||
backgroundDetectionObserver.register(this)
|
||||
state = State.RUNNING
|
||||
while (state != State.KILLING) {
|
||||
if (!networkConnectivityChecker.isConnected() || state == State.PAUSED) {
|
||||
updateStateTo(SyncState.RUNNING(catchingUp = true))
|
||||
|
||||
while (state != SyncState.KILLING) {
|
||||
if (!networkConnectivityChecker.isConnected() || state == SyncState.PAUSED) {
|
||||
Timber.v("Waiting...")
|
||||
synchronized(lock) {
|
||||
lock.wait()
|
||||
@ -133,7 +127,7 @@ internal class SyncThread(private val syncTask: SyncTask,
|
||||
if (failure is Failure.ServerError
|
||||
&& (failure.error.code == MatrixError.UNKNOWN_TOKEN || failure.error.code == MatrixError.MISSING_TOKEN)) {
|
||||
// No token or invalid token, stop the thread
|
||||
state = State.KILLING
|
||||
updateStateTo(SyncState.KILLING)
|
||||
}
|
||||
|
||||
latch.countDown()
|
||||
@ -141,16 +135,23 @@ internal class SyncThread(private val syncTask: SyncTask,
|
||||
|
||||
})
|
||||
.executeBy(taskExecutor)
|
||||
|
||||
latch.await()
|
||||
if (state is SyncState.RUNNING) {
|
||||
updateStateTo(SyncState.RUNNING(catchingUp = false))
|
||||
}
|
||||
}
|
||||
}
|
||||
Timber.v("Sync killed")
|
||||
state = State.KILLED
|
||||
updateStateTo(SyncState.KILLED)
|
||||
backgroundDetectionObserver.unregister(this)
|
||||
networkConnectivityChecker.unregister(this)
|
||||
}
|
||||
|
||||
private fun updateStateTo(newState: SyncState) {
|
||||
state = newState
|
||||
liveState.postValue(newState)
|
||||
}
|
||||
|
||||
override fun onConnect() {
|
||||
synchronized(lock) {
|
||||
lock.notify()
|
||||
|
Reference in New Issue
Block a user