From 5a8a9c43fa6ec758b8bab37340605b30fa8dfcfc Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Wed, 27 Mar 2024 16:34:13 -0300 Subject: [PATCH] feat: only auto sync if there are changes this avoids blocking the UI with the sync dialog if syncing isn't necessary --- .../main/java/com/ichi2/anki/DeckPicker.kt | 42 +++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt index e05955cbd06a..56d0e43b8f36 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt @@ -62,6 +62,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import anki.collection.OpChanges +import anki.sync.SyncStatusResponse import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.progressindicator.CircularProgressIndicator import com.google.android.material.snackbar.BaseTransientBottomBar @@ -115,6 +116,7 @@ import com.ichi2.anki.snackbar.showSnackbar import com.ichi2.anki.ui.dialogs.storageMigrationFailedDialogIsShownOrPending import com.ichi2.anki.utils.SECONDS_PER_DAY import com.ichi2.anki.widgets.DeckAdapter +import com.ichi2.anki.worker.SyncMediaWorker import com.ichi2.annotations.NeedsTest import com.ichi2.async.* import com.ichi2.compat.CompatHelper.Companion.getSerializableCompat @@ -1200,7 +1202,27 @@ open class DeckPicker : } } - private fun automaticSync() { + private suspend fun automaticSync() { + /** + * @return whether there are collection changes to be sync. + * + * It DOES NOT include if there are media to be synced. + */ + suspend fun areThereChangesToSync(): Boolean { + val auth = syncAuth() ?: return false + val status = withContext(Dispatchers.IO) { + CollectionManager.getBackend().syncStatus(auth) + }.required + + return when (status) { + SyncStatusResponse.Required.NO_CHANGES, + SyncStatusResponse.Required.UNRECOGNIZED, + null -> false + SyncStatusResponse.Required.FULL_SYNC, + SyncStatusResponse.Required.NORMAL_SYNC -> true + } + } + fun syncIntervalPassed(): Boolean { val lastSyncTime = sharedPrefs().getLong("lastSyncTime", 0) val automaticSyncIntervalInMS = AUTOMATIC_SYNC_MINIMAL_INTERVAL_IN_MINUTES * 60 * 1000 @@ -1219,6 +1241,13 @@ open class DeckPicker : !syncIntervalPassed() -> Timber.d("autoSync: sync interval not passed") !isLoggedIn() -> Timber.d("autoSync: not logged in") mediaMigrationIsInProgress(this) -> Timber.d("autoSync: migrating storage") + !areThereChangesToSync() -> { + Timber.d("autoSync: no collection changes to sync. Syncing media if set") + if (shouldFetchMedia(sharedPrefs())) { + val auth = syncAuth() ?: return + SyncMediaWorker.start(this, auth) + } + } else -> { Timber.i("autoSync: start") sync() @@ -1241,8 +1270,11 @@ open class DeckPicker : false ) || backButtonPressedToExit ) { - automaticSync() - finish() + launchCatchingTask { + automaticSync() + }.invokeOnCompletion { + finish() + } } else { showSnackbar(R.string.back_pressed_once, Snackbar.LENGTH_SHORT) } @@ -1322,7 +1354,9 @@ open class DeckPicker : dialogHandler.sendMessage(OneWaySyncDialog(message).toMessage()) } } - automaticSync() + launchCatchingTask { + automaticSync() + } } private fun showCollectionErrorDialog() {