diff --git a/changelog.d/6341.bugfix b/changelog.d/6341.bugfix new file mode 100644 index 0000000000..6866d8c89d --- /dev/null +++ b/changelog.d/6341.bugfix @@ -0,0 +1 @@ +Fixed issues with reporting sync state events from different threads diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt index 5b2bf651af..71f7ab8494 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/SyncService.kt @@ -60,9 +60,9 @@ interface SyncService { fun getSyncStateLive(): LiveData /** - * Get the [SyncRequestState] as a LiveData. + * Get the [SyncRequestState] as a SharedFlow. */ - fun getSyncRequestStateLive(): LiveData + fun getSyncRequestStateFlow(): SharedFlow /** * This method returns a flow of SyncResponse. New value will be pushed through the sync thread. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt index 37869b88f9..691dd7b20d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/DefaultSyncService.kt @@ -16,8 +16,6 @@ package org.matrix.android.sdk.internal.session.sync -import androidx.lifecycle.LiveData -import org.matrix.android.sdk.api.session.sync.SyncRequestState import org.matrix.android.sdk.api.session.sync.SyncService import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.di.WorkManagerProvider @@ -75,9 +73,7 @@ internal class DefaultSyncService @Inject constructor( override fun getSyncState() = getSyncThread().currentState() - override fun getSyncRequestStateLive(): LiveData { - return syncRequestStateTracker.syncRequestState - } + override fun getSyncRequestStateFlow() = syncRequestStateTracker.syncRequestState override fun hasAlreadySynced(): Boolean { return syncTokenStore.getLastToken() != null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncRequestStateTracker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncRequestStateTracker.kt index bcc5fcf9ab..03ce8cb3f2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncRequestStateTracker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncRequestStateTracker.kt @@ -16,23 +16,26 @@ package org.matrix.android.sdk.internal.session.sync -import androidx.lifecycle.MutableLiveData +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.sync.InitialSyncStep import org.matrix.android.sdk.api.session.sync.SyncRequestState import org.matrix.android.sdk.internal.session.SessionScope import javax.inject.Inject @SessionScope -internal class SyncRequestStateTracker @Inject constructor() : - ProgressReporter { +internal class SyncRequestStateTracker @Inject constructor( + private val coroutineScope: CoroutineScope +) : ProgressReporter { - val syncRequestState = MutableLiveData() + val syncRequestState = MutableSharedFlow() private var rootTask: TaskInfo? = null // Only to be used for incremental sync fun setSyncRequestState(newSyncRequestState: SyncRequestState.IncrementalSyncRequestState) { - syncRequestState.postValue(newSyncRequestState) + emitSyncState(newSyncRequestState) } /** @@ -42,7 +45,9 @@ internal class SyncRequestStateTracker @Inject constructor() : initialSyncStep: InitialSyncStep, totalProgress: Int ) { - endAll() + if (rootTask != null) { + endAll() + } rootTask = TaskInfo(initialSyncStep, totalProgress, null, 1F) reportProgress(0F) } @@ -71,7 +76,7 @@ internal class SyncRequestStateTracker @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 - syncRequestState.postValue(SyncRequestState.InitialSyncProgressing(leaf.initialSyncStep, root.currentProgress.toInt())) + emitSyncState(SyncRequestState.InitialSyncProgressing(leaf.initialSyncStep, root.currentProgress.toInt())) } } } @@ -86,13 +91,19 @@ internal class SyncRequestStateTracker @Inject constructor() : // And close it endedTask.parent.child = null } else { - syncRequestState.postValue(SyncRequestState.Idle) + emitSyncState(SyncRequestState.Idle) } } } fun endAll() { rootTask = null - syncRequestState.postValue(SyncRequestState.Idle) + emitSyncState(SyncRequestState.Idle) + } + + private fun emitSyncState(state: SyncRequestState) { + coroutineScope.launch { + syncRequestState.emit(state) + } } } diff --git a/vector/src/main/java/im/vector/app/AppStateHandler.kt b/vector/src/main/java/im/vector/app/AppStateHandler.kt index e1b8bfc474..e18b576637 100644 --- a/vector/src/main/java/im/vector/app/AppStateHandler.kt +++ b/vector/src/main/java/im/vector/app/AppStateHandler.kt @@ -18,7 +18,6 @@ package im.vector.app import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.asFlow import arrow.core.Option import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.utils.BehaviorDataSource @@ -114,8 +113,7 @@ class AppStateHandler @Inject constructor( } private fun observeSyncStatus(session: Session) { - session.syncService().getSyncRequestStateLive() - .asFlow() + session.syncService().getSyncRequestStateFlow() .filterIsInstance() .map { session.spaceService().getRootSpaceSummaries().size } .distinctUntilChanged() diff --git a/vector/src/main/java/im/vector/app/AutoRageShaker.kt b/vector/src/main/java/im/vector/app/AutoRageShaker.kt index dc561aa821..bb3c8bcf05 100644 --- a/vector/src/main/java/im/vector/app/AutoRageShaker.kt +++ b/vector/src/main/java/im/vector/app/AutoRageShaker.kt @@ -17,7 +17,6 @@ package im.vector.app import android.content.SharedPreferences -import androidx.lifecycle.asFlow import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.features.rageshake.BugReporter import im.vector.app.features.rageshake.ReportType @@ -261,8 +260,7 @@ class AutoRageShaker @Inject constructor( this.currentActiveSessionId = sessionId hasSynced = session.syncService().hasAlreadySynced() - session.syncService().getSyncRequestStateLive() - .asFlow() + session.syncService().getSyncRequestStateFlow() .onEach { hasSynced = it !is SyncRequestState.InitialSyncProgressing } diff --git a/vector/src/main/java/im/vector/app/features/analytics/accountdata/AnalyticsAccountDataViewModel.kt b/vector/src/main/java/im/vector/app/features/analytics/accountdata/AnalyticsAccountDataViewModel.kt index 05358decc9..28929127e1 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/accountdata/AnalyticsAccountDataViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/accountdata/AnalyticsAccountDataViewModel.kt @@ -16,7 +16,6 @@ package im.vector.app.features.analytics.accountdata -import androidx.lifecycle.asFlow import com.airbnb.mvrx.MavericksViewModelFactory import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -66,7 +65,7 @@ class AnalyticsAccountDataViewModel @AssistedInject constructor( private fun observeInitSync() { combine( - session.syncService().getSyncRequestStateLive().asFlow(), + session.syncService().getSyncRequestStateFlow(), analytics.getUserConsent(), analytics.getAnalyticsId() ) { status, userConsent, analyticsId -> diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt index b45e6fbcb0..e67d483983 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt @@ -16,7 +16,6 @@ package im.vector.app.features.home -import androidx.lifecycle.asFlow import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.MavericksViewModelFactory import com.airbnb.mvrx.ViewModelContext @@ -218,8 +217,7 @@ class HomeActivityViewModel @AssistedInject constructor( private fun observeInitialSync() { val session = activeSessionHolder.getSafeActiveSession() ?: return - session.syncService().getSyncRequestStateLive() - .asFlow() + session.syncService().getSyncRequestStateFlow() .onEach { status -> when (status) { is SyncRequestState.Idle -> { diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt index 357d2b7c69..787458993f 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt @@ -198,8 +198,7 @@ class HomeDetailViewModel @AssistedInject constructor( copy(syncState = syncState) } - session.syncService().getSyncRequestStateLive() - .asFlow() + session.syncService().getSyncRequestStateFlow() .filterIsInstance() .setOnEach { copy(incrementalSyncRequestState = it) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt index c73ed3b672..69af183885 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt @@ -18,7 +18,6 @@ package im.vector.app.features.home.room.detail import android.net.Uri import androidx.annotation.IdRes -import androidx.lifecycle.asFlow import com.airbnb.mvrx.Async import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading @@ -1152,8 +1151,7 @@ class TimelineViewModel @AssistedInject constructor( copy(syncState = syncState) } - session.syncService().getSyncRequestStateLive() - .asFlow() + session.syncService().getSyncRequestStateFlow() .filterIsInstance() .setOnEach { copy(incrementalSyncRequestState = it)