mirror of
https://github.com/bitfireAT/davx5-ose
synced 2024-07-23 11:39:15 +00:00
Implement proper network check before manual sync (bitfireAT/davx5#259)
* Implement proper network check before manual sync Do a proper connectivity check, to show a message to the user, about the sync being scheduled for when connectivity is available, before enqueueing the SyncWorker. * Update the sync status in accounts adapter to include pending syncs This is relevant for when a manual sync is triggered without connectivity. * Replace Toast by Snackbar * Replace ViewModel by AndroidViewModel --------- Co-authored-by: Ricki Hirner <hirner@bitfire.at>
This commit is contained in:
parent
5cbf14fa27
commit
2ebb40b152
|
@ -235,7 +235,13 @@ class AccountListFragment: Fragment() {
|
|||
|
||||
// Accounts
|
||||
private val accountsUpdated = MutableLiveData<Boolean>()
|
||||
private val syncWorkersActive = SyncWorker.exists(application, listOf(WorkInfo.State.RUNNING))
|
||||
private val syncWorkersActive = SyncWorker.exists(
|
||||
application,
|
||||
listOf(
|
||||
WorkInfo.State.RUNNING,
|
||||
WorkInfo.State.ENQUEUED
|
||||
)
|
||||
)
|
||||
|
||||
val accounts = object : MediatorLiveData<List<AccountInfo>>() {
|
||||
init {
|
||||
|
|
|
@ -6,23 +6,28 @@ package at.bitfire.davdroid.ui
|
|||
|
||||
import android.accounts.AccountManager
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import android.content.pm.ShortcutManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.widget.Toast
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.view.GravityCompat
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import at.bitfire.davdroid.R
|
||||
import at.bitfire.davdroid.databinding.ActivityAccountsBinding
|
||||
import at.bitfire.davdroid.settings.SettingsManager
|
||||
import at.bitfire.davdroid.syncadapter.SyncWorker
|
||||
import at.bitfire.davdroid.ui.intro.IntroActivity
|
||||
import at.bitfire.davdroid.ui.setup.LoginActivity
|
||||
import com.google.android.material.navigation.NavigationView
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -38,6 +43,7 @@ class AccountsActivity: AppCompatActivity(), NavigationView.OnNavigationItemSele
|
|||
@Inject lateinit var accountsDrawerHandler: AccountsDrawerHandler
|
||||
|
||||
private lateinit var binding: ActivityAccountsBinding
|
||||
val model by viewModels<Model>()
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -110,16 +116,28 @@ class AccountsActivity: AppCompatActivity(), NavigationView.OnNavigationItemSele
|
|||
if (Build.VERSION.SDK_INT >= 25)
|
||||
getSystemService<ShortcutManager>()?.reportShortcutUsed(UiUtils.SHORTCUT_SYNC_ALL)
|
||||
|
||||
// Check we are connected
|
||||
if (!SyncWorker.wifiAvailable(applicationContext)) {
|
||||
Toast.makeText(this, R.string.no_internet_connection, Toast.LENGTH_LONG).show()
|
||||
return
|
||||
// Notify user that sync will get enqueued if we're not connected to the internet
|
||||
model.networkAvailable.value?.let { networkAvailable ->
|
||||
if (!networkAvailable)
|
||||
Snackbar.make(binding.drawerLayout, R.string.no_internet_sync_scheduled, Snackbar.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
// Enqueue sync worker for all accounts and authorities
|
||||
// Enqueue sync worker for all accounts and authorities. Will sync once internet is available
|
||||
val accounts = allAccounts()
|
||||
for (account in accounts)
|
||||
SyncWorker.enqueueAllAuthorities(this, account)
|
||||
}
|
||||
|
||||
|
||||
@HiltViewModel
|
||||
class Model @Inject constructor(
|
||||
application: Application,
|
||||
val settings: SettingsManager,
|
||||
warnings: AppWarningsManager
|
||||
): AndroidViewModel(application) {
|
||||
|
||||
val networkAvailable = warnings.networkAvailable
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ package at.bitfire.davdroid.ui.account
|
|||
import android.accounts.Account
|
||||
import android.accounts.AccountManager
|
||||
import android.accounts.OnAccountsUpdateListener
|
||||
import android.content.Context
|
||||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
|
@ -28,12 +28,13 @@ import at.bitfire.davdroid.db.Service
|
|||
import at.bitfire.davdroid.log.Logger
|
||||
import at.bitfire.davdroid.settings.AccountSettings
|
||||
import at.bitfire.davdroid.syncadapter.SyncWorker
|
||||
import at.bitfire.davdroid.ui.AppWarningsManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.NonCancellable
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -86,10 +87,14 @@ class AccountActivity: AppCompatActivity() {
|
|||
tabsAdapter.calDavSvcId = it
|
||||
})
|
||||
|
||||
binding.sync.setOnClickListener {
|
||||
// enqueue sync worker for all authorities of this account
|
||||
SyncWorker.enqueueAllAuthorities(this, model.account)
|
||||
}
|
||||
// "Sync now" button
|
||||
model.networkAvailable.observe(this, Observer { networkAvailable ->
|
||||
binding.sync.setOnClickListener {
|
||||
if (!networkAvailable)
|
||||
Snackbar.make(binding.sync, R.string.no_internet_sync_scheduled, Snackbar.LENGTH_LONG).show()
|
||||
SyncWorker.enqueueAllAuthorities(this, model.account)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
|
@ -241,25 +246,28 @@ class AccountActivity: AppCompatActivity() {
|
|||
// model
|
||||
|
||||
class Model @AssistedInject constructor(
|
||||
@ApplicationContext val context: Context,
|
||||
application: Application,
|
||||
val db: AppDatabase,
|
||||
@Assisted val account: Account
|
||||
): ViewModel(), OnAccountsUpdateListener {
|
||||
@Assisted val account: Account,
|
||||
warnings: AppWarningsManager
|
||||
): AndroidViewModel(application), OnAccountsUpdateListener {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(account: Account): Model
|
||||
}
|
||||
|
||||
val accountManager = AccountManager.get(context)!!
|
||||
val accountSettings by lazy { AccountSettings(context, account) }
|
||||
val accountManager: AccountManager = AccountManager.get(application)
|
||||
val accountSettings by lazy { AccountSettings(application, account) }
|
||||
|
||||
val accountExists = MutableLiveData<Boolean>()
|
||||
val cardDavService = db.serviceDao().getIdByAccountAndType(account.name, Service.TYPE_CARDDAV)
|
||||
val calDavService = db.serviceDao().getIdByAccountAndType(account.name, Service.TYPE_CALDAV)
|
||||
|
||||
val showOnlyPersonal = MutableLiveData<Boolean>()
|
||||
val showOnlyPersonal_writable = MutableLiveData<Boolean>()
|
||||
val showOnlyPersonalWritable = MutableLiveData<Boolean>()
|
||||
|
||||
val networkAvailable = warnings.networkAvailable
|
||||
|
||||
|
||||
init {
|
||||
|
@ -267,7 +275,7 @@ class AccountActivity: AppCompatActivity() {
|
|||
viewModelScope.launch(Dispatchers.IO) {
|
||||
accountSettings.getShowOnlyPersonal().let { (value, locked) ->
|
||||
showOnlyPersonal.postValue(value)
|
||||
showOnlyPersonal_writable.postValue(locked)
|
||||
showOnlyPersonalWritable.postValue(locked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ abstract class CollectionsFragment: Fragment(), SwipeRefreshLayout.OnRefreshList
|
|||
accountModel.showOnlyPersonal.value?.let { value ->
|
||||
showOnlyPersonal.isChecked = value
|
||||
}
|
||||
accountModel.showOnlyPersonal_writable.value?.let { writable ->
|
||||
accountModel.showOnlyPersonalWritable.value?.let { writable ->
|
||||
showOnlyPersonal.isEnabled = writable
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<string name="help">Help</string>
|
||||
<string name="manage_accounts">Manage accounts</string>
|
||||
<string name="share">Share</string>
|
||||
<string name="no_internet_connection">No internet connection</string>
|
||||
<string name="no_internet_sync_scheduled">No internet, scheduling sync</string>
|
||||
|
||||
<string name="database_destructive_migration_title">Database corrupted</string>
|
||||
<string name="database_destructive_migration_text">All accounts have been removed locally.</string>
|
||||
|
|
Loading…
Reference in a new issue