Use coroutines in account and list settings

pull/1052/head
Alex Baker 4 years ago
parent 320623045e
commit 39305d1107

@ -61,19 +61,19 @@ class TaskDeleter @Inject constructor(
localBroadcastManager.broadcastRefreshList()
}
fun delete(list: GoogleTaskAccount) = runBlocking {
suspend fun delete(list: GoogleTaskAccount) {
val tasks = deletionDao.delete(list)
delete(tasks)
localBroadcastManager.broadcastRefreshList()
}
fun delete(list: CaldavCalendar) = runBlocking {
suspend fun delete(list: CaldavCalendar) {
val tasks = deletionDao.delete(list)
delete(tasks)
localBroadcastManager.broadcastRefreshList()
}
fun delete(list: CaldavAccount) = runBlocking {
suspend fun delete(list: CaldavAccount) {
val tasks = deletionDao.delete(list)
delete(tasks)
localBroadcastManager.broadcastRefreshList()

@ -7,9 +7,11 @@ import android.view.MenuItem
import android.view.View
import android.widget.TextView
import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.lifecycleScope
import butterknife.BindView
import butterknife.ButterKnife
import butterknife.OnClick
import kotlinx.coroutines.launch
import org.tasks.R
import org.tasks.dialogs.ColorPalettePicker
import org.tasks.dialogs.ColorPalettePicker.Companion.newColorPalette
@ -54,7 +56,7 @@ abstract class BaseListSettingsActivity : ThemedInjectingAppCompatActivity(), Ic
}
toolbar.title = toolbarTitle
toolbar.navigationIcon = getDrawable(R.drawable.ic_outline_save_24px)
toolbar.setNavigationOnClickListener { save() }
toolbar.setNavigationOnClickListener { lifecycleScope.launch { save() } }
if (!isNew) {
toolbar.inflateMenu(R.menu.menu_tag_settings)
}
@ -73,10 +75,10 @@ abstract class BaseListSettingsActivity : ThemedInjectingAppCompatActivity(), Ic
protected abstract val layout: Int
protected abstract fun hasChanges(): Boolean
protected abstract fun save()
protected abstract suspend fun save()
protected abstract val isNew: Boolean
protected abstract val toolbarTitle: String?
protected abstract fun delete()
protected abstract suspend fun delete()
protected open fun discard() {
if (!hasChanges()) {
finish()
@ -127,7 +129,7 @@ abstract class BaseListSettingsActivity : ThemedInjectingAppCompatActivity(), Ic
protected open fun promptDelete() {
dialogBuilder
.newDialog(R.string.delete_tag_confirmation, toolbarTitle)
.setPositiveButton(R.string.delete) { _, _ -> delete() }
.setPositiveButton(R.string.delete) { _, _ -> lifecycleScope.launch { delete() } }
.setNegativeButton(android.R.string.cancel, null)
.show()
}

@ -7,7 +7,7 @@ import org.tasks.ui.CompletableViewModel
class CreateListViewModel @ViewModelInject constructor(
private val invoker: GtasksInvoker) : CompletableViewModel<TaskList>() {
fun createList(account: String, name: String) {
suspend fun createList(account: String, name: String) {
run { invoker.forAccount(account).createGtaskList(name)!! }
}
}

@ -7,7 +7,7 @@ import org.tasks.ui.ActionViewModel
class DeleteListViewModel @ViewModelInject constructor(
private val invoker: GtasksInvoker) : ActionViewModel() {
fun deleteList(list: GoogleTaskList) {
suspend fun deleteList(list: GoogleTaskList) {
run { invoker.forAccount(list.account!!).deleteGtaskList(list.remoteId) }
}
}

@ -37,6 +37,7 @@ import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R
import org.tasks.Strings
import org.tasks.data.Filter
import org.tasks.data.FilterDao
import org.tasks.data.FilterDaoBlocking
import org.tasks.filters.FilterCriteriaProvider
import org.tasks.locale.Locale
@ -46,7 +47,7 @@ import kotlin.math.max
@AndroidEntryPoint
class FilterSettingsActivity : BaseListSettingsActivity() {
@Inject lateinit var filterDao: FilterDaoBlocking
@Inject lateinit var filterDao: FilterDao
@Inject lateinit var locale: Locale
@Inject lateinit var database: Database
@Inject lateinit var filterCriteriaProvider: FilterCriteriaProvider
@ -224,7 +225,7 @@ class FilterSettingsActivity : BaseListSettingsActivity() {
nameLayout.error = null
}
override fun save() {
override suspend fun save() {
val newName = newName
if (Strings.isNullOrEmpty(newName)) {
nameLayout.error = getString(R.string.name_cannot_be_empty)
@ -277,7 +278,7 @@ class FilterSettingsActivity : BaseListSettingsActivity() {
override val layout: Int
get() = R.layout.filter_settings_activity
override fun delete() {
override suspend fun delete() {
filterDao.delete(filter!!.id)
setResult(
Activity.RESULT_OK, Intent(TaskListFragment.ACTION_DELETED).putExtra(TOKEN_FILTER, filter))

@ -15,7 +15,6 @@ import com.google.api.services.tasks.model.TaskList
import com.todoroo.astrid.activity.MainActivity
import com.todoroo.astrid.activity.TaskListFragment
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.gtasks.GtasksListService
import com.todoroo.astrid.gtasks.api.GtasksInvoker
import com.todoroo.astrid.service.TaskDeleter
import dagger.hilt.android.AndroidEntryPoint
@ -24,15 +23,14 @@ import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import org.tasks.data.GoogleTaskAccount
import org.tasks.data.GoogleTaskList
import org.tasks.data.GoogleTaskListDaoBlocking
import org.tasks.data.GoogleTaskListDao
import timber.log.Timber
import javax.inject.Inject
@AndroidEntryPoint
class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
@Inject @ApplicationContext lateinit var context: Context
@Inject lateinit var googleTaskListDao: GoogleTaskListDaoBlocking
@Inject lateinit var gtasksListService: GtasksListService
@Inject lateinit var googleTaskListDao: GoogleTaskListDao
@Inject lateinit var taskDeleter: TaskDeleter
@Inject lateinit var gtasksInvoker: GtasksInvoker
@ -93,7 +91,7 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
private fun requestInProgress() = progressView.visibility == View.VISIBLE
override fun save() {
override suspend fun save() {
if (requestInProgress()) {
return
}
@ -141,7 +139,7 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
}
}
override fun delete() {
override suspend fun delete() {
showProgressIndicator()
deleteListViewModel.deleteList(gtasksList)
}
@ -167,7 +165,7 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
private fun nameChanged() = newName != gtasksList.title
private fun onListCreated(taskList: TaskList) {
private suspend fun onListCreated(taskList: TaskList) {
gtasksList.remoteId = taskList.id
gtasksList.title = taskList.title
gtasksList.setColor(selectedColor)
@ -176,10 +174,9 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
setResult(
Activity.RESULT_OK, Intent().putExtra(MainActivity.OPEN_FILTER, GtasksFilter(gtasksList)))
finish()
return
}
private fun onListDeleted(deleted: Boolean) {
private suspend fun onListDeleted(deleted: Boolean) {
if (deleted) {
taskDeleter.delete(gtasksList)
setResult(Activity.RESULT_OK, Intent(TaskListFragment.ACTION_DELETED))
@ -187,7 +184,7 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
}
}
private fun onListRenamed(taskList: TaskList) {
private suspend fun onListRenamed(taskList: TaskList) {
gtasksList.title = taskList.title
gtasksList.setColor(selectedColor)
gtasksList.setIcon(selectedIcon)
@ -197,7 +194,6 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
Intent(TaskListFragment.ACTION_RELOAD)
.putExtra(MainActivity.OPEN_FILTER, GtasksFilter(gtasksList)))
finish()
return
}
private fun requestFailed(error: Throwable) {

@ -12,7 +12,7 @@ import com.todoroo.astrid.activity.TaskListFragment
import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import org.tasks.data.LocationDaoBlocking
import org.tasks.data.LocationDao
import org.tasks.data.Place
import org.tasks.filters.PlaceFilter
import org.tasks.location.MapFragment
@ -28,7 +28,7 @@ class PlaceSettingsActivity : BaseListSettingsActivity(), MapFragment.MapFragmen
@BindView(R.id.name) lateinit var name: TextInputEditText
@BindView(R.id.name_layout) lateinit var nameLayout: TextInputLayout
@Inject lateinit var locationDao: LocationDaoBlocking
@Inject lateinit var locationDao: LocationDao
@Inject lateinit var map: MapFragment
private lateinit var place: Place
@ -71,7 +71,7 @@ class PlaceSettingsActivity : BaseListSettingsActivity(), MapFragment.MapFragmen
nameLayout.error = null
}
override fun save() {
override suspend fun save() {
val newName: String = name.text.toString()
if (isNullOrEmpty(newName)) {
@ -96,7 +96,7 @@ class PlaceSettingsActivity : BaseListSettingsActivity(), MapFragment.MapFragmen
override val toolbarTitle: String?
get() = place.address ?: place.displayName
override fun delete() {
override suspend fun delete() {
locationDao.deleteGeofencesByPlace(place.uid!!)
locationDao.delete(place)
setResult(Activity.RESULT_OK, Intent(TaskListFragment.ACTION_DELETED))

@ -8,7 +8,7 @@ import org.tasks.ui.CompletableViewModel
class RenameListViewModel @ViewModelInject constructor(
private val invoker: GtasksInvoker) : CompletableViewModel<TaskList>() {
fun renameList(list: GoogleTaskList, name: String) {
suspend fun renameList(list: GoogleTaskList, name: String) {
run { invoker.forAccount(list.account!!).renameGtaskList(list.remoteId, name)!! }
}
}

@ -21,15 +21,15 @@ import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import org.tasks.data.TagDaoBlocking
import org.tasks.data.TagDao
import org.tasks.data.TagData
import org.tasks.data.TagDataDaoBlocking
import org.tasks.data.TagDataDao
import javax.inject.Inject
@AndroidEntryPoint
class TagSettingsActivity : BaseListSettingsActivity() {
@Inject lateinit var tagDataDao: TagDataDaoBlocking
@Inject lateinit var tagDao: TagDaoBlocking
@Inject lateinit var tagDataDao: TagDataDao
@Inject lateinit var tagDao: TagDao
@BindView(R.id.name)
lateinit var name: TextInputEditText
@ -78,12 +78,12 @@ class TagSettingsActivity : BaseListSettingsActivity() {
private val newName: String
get() = name.text.toString().trim { it <= ' ' }
private fun clashes(newName: String): Boolean {
private suspend fun clashes(newName: String): Boolean {
return ((isNewTag || !newName.equals(tagData.name, ignoreCase = true))
&& tagDataDao.getTagByName(newName) != null)
}
override fun save() {
override suspend fun save() {
val newName = newName
if (isNullOrEmpty(newName)) {
nameLayout.error = getString(R.string.name_cannot_be_empty)
@ -132,7 +132,7 @@ class TagSettingsActivity : BaseListSettingsActivity() {
override val layout: Int
get() = R.layout.activity_tag_settings
override fun delete() {
override suspend fun delete() {
val uuid = tagData.remoteId
tagDataDao.delete(tagData)
setResult(

@ -5,7 +5,7 @@ import org.tasks.ui.CompletableViewModel
class AddCaldavAccountViewModel @ViewModelInject constructor(
private val client: CaldavClient) : CompletableViewModel<String>() {
fun addAccount(url: String, username: String, password: String) {
suspend fun addAccount(url: String, username: String, password: String) {
run { client.setForeground().forUrl(url, username, password).homeSet }
}
}

@ -12,6 +12,7 @@ import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.annotation.StringRes
import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.lifecycleScope
import at.bitfire.dav4jvm.exception.HttpException
import butterknife.ButterKnife
import butterknife.OnFocusChange
@ -20,12 +21,13 @@ import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.service.TaskDeleter
import kotlinx.coroutines.launch
import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import org.tasks.billing.Inventory
import org.tasks.billing.PurchaseActivity
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavDaoBlocking
import org.tasks.data.CaldavDao
import org.tasks.databinding.ActivityCaldavAccountSettingsBinding
import org.tasks.dialogs.DialogBuilder
import org.tasks.injection.ThemedInjectingAppCompatActivity
@ -39,7 +41,7 @@ import java.net.URISyntaxException
import javax.inject.Inject
abstract class BaseCaldavAccountSettingsActivity : ThemedInjectingAppCompatActivity(), Toolbar.OnMenuItemClickListener {
@Inject lateinit var caldavDao: CaldavDaoBlocking
@Inject lateinit var caldavDao: CaldavDao
@Inject lateinit var encryption: KeyStoreEncryption
@Inject lateinit var dialogBuilder: DialogBuilder
@Inject lateinit var taskDeleter: TaskDeleter
@ -169,9 +171,9 @@ abstract class BaseCaldavAccountSettingsActivity : ThemedInjectingAppCompatActiv
protected abstract val newPassword: String?
private fun save() {
private fun save() = lifecycleScope.launch {
if (requestInProgress()) {
return
return@launch
}
val username = newUsername
val url = newURL
@ -217,7 +219,7 @@ abstract class BaseCaldavAccountSettingsActivity : ThemedInjectingAppCompatActiv
failed = true
}
when {
failed -> return
failed -> return@launch
caldavAccount == null -> {
showProgressIndicator()
addAccount(url, username, password!!)
@ -235,9 +237,9 @@ abstract class BaseCaldavAccountSettingsActivity : ThemedInjectingAppCompatActiv
}
}
protected abstract fun addAccount(url: String, username: String, password: String)
protected abstract fun updateAccount(url: String, username: String, password: String?)
protected abstract fun updateAccount()
protected abstract suspend fun addAccount(url: String, username: String, password: String)
protected abstract suspend fun updateAccount(url: String, username: String, password: String?)
protected abstract suspend fun updateAccount()
protected abstract val helpUrl: String?
protected fun requestFailed(t: Throwable) {
@ -313,12 +315,12 @@ abstract class BaseCaldavAccountSettingsActivity : ThemedInjectingAppCompatActiv
dialogBuilder
.newDialog()
.setMessage(R.string.logout_warning, caldavAccount!!.name)
.setPositiveButton(R.string.remove) { _, _ -> removeAccount() }
.setPositiveButton(R.string.remove) { _, _ -> lifecycleScope.launch { removeAccount() } }
.setNegativeButton(android.R.string.cancel, null)
.show()
}
protected open fun removeAccount() {
protected open suspend fun removeAccount() {
taskDeleter.delete(caldavAccount!!)
setResult(Activity.RESULT_OK)
finish()

@ -24,13 +24,14 @@ import org.tasks.Strings.isNullOrEmpty
import org.tasks.activities.BaseListSettingsActivity
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavCalendar
import org.tasks.data.CaldavDaoBlocking
import org.tasks.data.CaldavDao
import org.tasks.data.runBlocking
import org.tasks.ui.DisplayableException
import java.net.ConnectException
import javax.inject.Inject
abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
@Inject lateinit var caldavDao: CaldavDaoBlocking
@Inject lateinit var caldavDao: CaldavDao
@Inject lateinit var taskDeleter: TaskDeleter
@BindView(R.id.root_layout)
@ -58,7 +59,7 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
caldavAccount = if (caldavCalendar == null) {
intent.getParcelableExtra(EXTRA_CALDAV_ACCOUNT)!!
} else {
caldavDao.getAccountByUuid(caldavCalendar!!.account!!)!!
runBlocking { caldavDao.getAccountByUuid(caldavCalendar!!.account!!)!! }
}
if (savedInstanceState == null) {
if (caldavCalendar != null) {
@ -86,7 +87,7 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
nameLayout.error = null
}
override fun save() {
override suspend fun save() {
if (requestInProgress()) {
return
}
@ -108,12 +109,12 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
}
}
protected abstract fun createCalendar(caldavAccount: CaldavAccount, name: String, color: Int)
protected abstract suspend fun createCalendar(caldavAccount: CaldavAccount, name: String, color: Int)
protected abstract fun updateNameAndColor(
protected abstract suspend fun updateNameAndColor(
account: CaldavAccount, calendar: CaldavCalendar, name: String, color: Int)
protected abstract fun deleteCalendar(
protected abstract suspend fun deleteCalendar(
caldavAccount: CaldavAccount, caldavCalendar: CaldavCalendar)
private fun showProgressIndicator() {
@ -153,7 +154,7 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
snackbar.show()
}
protected fun createSuccessful(url: String?) {
protected suspend fun createSuccessful(url: String?) {
val caldavCalendar = CaldavCalendar()
caldavCalendar.uuid = UUIDHelper.newUUID()
caldavCalendar.account = caldavAccount.uuid
@ -166,10 +167,9 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
Activity.RESULT_OK,
Intent().putExtra(MainActivity.OPEN_FILTER, CaldavFilter(caldavCalendar)))
finish()
return
}
protected fun updateCalendar() {
protected suspend fun updateCalendar() {
caldavCalendar!!.name = newName
caldavCalendar!!.color = selectedColor
caldavCalendar!!.setIcon(selectedIcon)
@ -179,7 +179,6 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
Intent(TaskListFragment.ACTION_RELOAD)
.putExtra(MainActivity.OPEN_FILTER, CaldavFilter(caldavCalendar)))
finish()
return
}
override fun hasChanges(): Boolean {
@ -219,12 +218,12 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
}
}
override fun delete() {
override suspend fun delete() {
showProgressIndicator()
deleteCalendar(caldavAccount, caldavCalendar!!)
}
protected fun onDeleted(deleted: Boolean) {
protected suspend fun onDeleted(deleted: Boolean) {
if (deleted) {
taskDeleter.delete(caldavCalendar!!)
setResult(Activity.RESULT_OK, Intent(TaskListFragment.ACTION_DELETED))

@ -24,7 +24,7 @@ class CaldavAccountSettingsActivity : BaseCaldavAccountSettingsActivity(), Toolb
override val description: Int
get() = R.string.caldav_account_description
private fun addAccount(principal: String) {
private suspend fun addAccount(principal: String) {
hideProgressIndicator()
Timber.d("Found principal: %s", principal)
val newAccount = CaldavAccount()
@ -38,7 +38,7 @@ class CaldavAccountSettingsActivity : BaseCaldavAccountSettingsActivity(), Toolb
finish()
}
private fun updateAccount(principal: String?) {
private suspend fun updateAccount(principal: String?) {
hideProgressIndicator()
caldavAccount!!.name = newName
caldavAccount!!.url = principal
@ -53,17 +53,14 @@ class CaldavAccountSettingsActivity : BaseCaldavAccountSettingsActivity(), Toolb
finish()
}
override fun addAccount(url: String, username: String, password: String) {
addCaldavAccountViewModel.addAccount(url, username, password)
}
override suspend fun addAccount(url: String, username: String, password: String) =
addCaldavAccountViewModel.addAccount(url, username, password)
override fun updateAccount(url: String, username: String, password: String?) {
updateCaldavAccountViewModel.updateCaldavAccount(url, username, password)
}
override suspend fun updateAccount(url: String, username: String, password: String?) =
updateCaldavAccountViewModel.updateCaldavAccount(url, username, password)
override fun updateAccount() {
updateAccount(caldavAccount!!.url)
}
override suspend fun updateAccount() =
updateAccount(caldavAccount!!.url)
override val newPassword: String?
get() {

@ -2,7 +2,9 @@ package org.tasks.caldav
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import org.tasks.R
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavCalendar
@ -18,18 +20,22 @@ class CaldavCalendarSettingsActivity : BaseCaldavCalendarSettingsActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
createCalendarViewModel.observe(this, this::createSuccessful, this::requestFailed)
deleteCalendarViewModel.observe(this, this::onDeleted, this::requestFailed)
updateCalendarViewModel.observe(this, { updateCalendar() }, this::requestFailed)
updateCalendarViewModel.observe(
this,
{ updateCalendar() },
this::requestFailed)
}
override fun createCalendar(caldavAccount: CaldavAccount, name: String, color: Int) =
override suspend fun createCalendar(caldavAccount: CaldavAccount, name: String, color: Int) =
createCalendarViewModel.createCalendar(caldavAccount, name, color)
override fun updateNameAndColor(
override suspend fun updateNameAndColor(
account: CaldavAccount, calendar: CaldavCalendar, name: String, color: Int) =
updateCalendarViewModel.updateCalendar(account, calendar, name, color)
override fun deleteCalendar(caldavAccount: CaldavAccount, caldavCalendar: CaldavCalendar) =
override suspend fun deleteCalendar(caldavAccount: CaldavAccount, caldavCalendar: CaldavCalendar) =
deleteCalendarViewModel.deleteCalendar(caldavAccount, caldavCalendar)
}

@ -6,7 +6,7 @@ import org.tasks.ui.CompletableViewModel
class CreateCalendarViewModel @ViewModelInject constructor(
private val client: CaldavClient): CompletableViewModel<String?>() {
fun createCalendar(account: CaldavAccount, name: String, color: Int) {
suspend fun createCalendar(account: CaldavAccount, name: String, color: Int) {
run { client.forAccount(account).makeCollection(name, color) }
}
}

@ -7,7 +7,7 @@ import org.tasks.ui.ActionViewModel
class DeleteCalendarViewModel @ViewModelInject constructor(
private val client: CaldavClient) : ActionViewModel() {
fun deleteCalendar(account: CaldavAccount, calendar: CaldavCalendar) {
suspend fun deleteCalendar(account: CaldavAccount, calendar: CaldavCalendar) {
run { client.forCalendar(account, calendar).deleteCollection() }
}
}

@ -6,6 +6,7 @@ import org.tasks.R
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavCalendar
import org.tasks.data.CaldavDao
import org.tasks.data.runBlocking
@AndroidEntryPoint
class LocalListSettingsActivity : BaseCaldavCalendarSettingsActivity() {
@ -17,16 +18,16 @@ class LocalListSettingsActivity : BaseCaldavCalendarSettingsActivity() {
super.onCreate(savedInstanceState)
toolbar.menu.findItem(R.id.delete)?.isVisible =
caldavDao.getCalendarsByAccount(CaldavDao.LOCAL).size > 1
runBlocking { caldavDao.getCalendarsByAccount(CaldavDao.LOCAL).size > 1 }
}
override fun createCalendar(caldavAccount: CaldavAccount, name: String, color: Int) =
override suspend fun createCalendar(caldavAccount: CaldavAccount, name: String, color: Int) =
createSuccessful(null)
override fun updateNameAndColor(
override suspend fun updateNameAndColor(
account: CaldavAccount, calendar: CaldavCalendar, name: String, color: Int) =
updateCalendar()
override fun deleteCalendar(caldavAccount: CaldavAccount, caldavCalendar: CaldavCalendar) =
override suspend fun deleteCalendar(caldavAccount: CaldavAccount, caldavCalendar: CaldavCalendar) =
onDeleted(true)
}

@ -5,7 +5,7 @@ import org.tasks.ui.CompletableViewModel
class UpdateCaldavAccountViewModel @ViewModelInject constructor(
private val client: CaldavClient) : CompletableViewModel<String>() {
fun updateCaldavAccount(url: String, username: String, password: String?) {
suspend fun updateCaldavAccount(url: String, username: String, password: String?) {
run { client.forUrl(url, username, password).homeSet }
}
}

@ -7,7 +7,7 @@ import org.tasks.ui.CompletableViewModel
class UpdateCalendarViewModel @ViewModelInject constructor(
private val client: CaldavClient) : CompletableViewModel<String?>() {
fun updateCalendar(account: CaldavAccount, calendar: CaldavCalendar, name: String, color: Int) {
suspend fun updateCalendar(account: CaldavAccount, calendar: CaldavCalendar, name: String, color: Int) {
run { client.forCalendar(account, calendar).updateCollection(name, color) }
}
}

@ -2,13 +2,12 @@ package org.tasks.etesync
import androidx.core.util.Pair
import androidx.hilt.lifecycle.ViewModelInject
import com.etesync.journalmanager.UserInfoManager
import com.etesync.journalmanager.UserInfoManager.UserInfo
import org.tasks.ui.CompletableViewModel
class AddEteSyncAccountViewModel @ViewModelInject constructor(
private val client: EteSyncClient): CompletableViewModel<Pair<UserInfo, String>>() {
fun addAccount(url: String, username: String, password: String) {
suspend fun addAccount(url: String, username: String, password: String) {
run {
client.setForeground()
val token = client.forUrl(url, username, null, null).getToken(password)

@ -6,7 +6,7 @@ import org.tasks.ui.CompletableViewModel
class CreateCalendarViewModel @ViewModelInject constructor(
private val client: EteSyncClient) : CompletableViewModel<String?>() {
fun createCalendar(account: CaldavAccount, name: String, color: Int) {
suspend fun createCalendar(account: CaldavAccount, name: String, color: Int) {
run { client.forAccount(account).makeCollection(name, color) }
}
}

@ -6,7 +6,7 @@ import org.tasks.ui.CompletableViewModel
class CreateUserInfoViewModel @ViewModelInject constructor(
private val client: EteSyncClient): CompletableViewModel<String>() {
fun createUserInfo(caldavAccount: CaldavAccount, derivedKey: String) {
suspend fun createUserInfo(caldavAccount: CaldavAccount, derivedKey: String) {
run {
client.forAccount(caldavAccount).createUserInfo(derivedKey)
derivedKey

@ -7,7 +7,7 @@ import org.tasks.ui.ActionViewModel
class DeleteCalendarViewModel @ViewModelInject constructor(
private val client: EteSyncClient) : ActionViewModel() {
fun deleteCalendar(account: CaldavAccount, calendar: CaldavCalendar) {
suspend fun deleteCalendar(account: CaldavAccount, calendar: CaldavCalendar) {
run { client.forAccount(account).deleteCollection(calendar) }
}
}

@ -8,6 +8,7 @@ import android.view.MenuItem
import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.lifecycleScope
import at.bitfire.dav4jvm.exception.HttpException
import butterknife.ButterKnife
import butterknife.OnTextChanged
@ -19,6 +20,7 @@ import com.etesync.journalmanager.Exceptions.VersionTooNewException
import com.etesync.journalmanager.UserInfoManager
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import org.tasks.data.CaldavAccount
@ -57,7 +59,7 @@ class EncryptionSettingsActivity : ThemedInjectingAppCompatActivity(), Toolbar.O
toolbar.inflateMenu(R.menu.menu_help)
toolbar.setOnMenuItemClickListener(this)
themeColor.apply(toolbar)
createUserInfoViewModel.observe(this, this::returnDerivedKey, this::requestFailed)
createUserInfoViewModel.observe(this, { returnDerivedKey(it) }, this::requestFailed)
if (createUserInfoViewModel.inProgress) {
showProgressIndicator()
}
@ -82,21 +84,21 @@ class EncryptionSettingsActivity : ThemedInjectingAppCompatActivity(), Toolbar.O
return
}
private fun save() {
private fun save() = lifecycleScope.launch {
if (requestInProgress()) {
return
return@launch
}
val encryptionPassword = newEncryptionPassword
val derivedKey = caldavAccount!!.getEncryptionPassword(encryption)
if (isNullOrEmpty(encryptionPassword) && isNullOrEmpty(derivedKey)) {
binding.encryptionPasswordLayout.error = getString(R.string.encryption_password_required)
return
return@launch
}
if (userInfo == null) {
val repeatEncryptionPassword = binding.repeatEncryptionPassword.text.toString().trim { it <= ' ' }
if (encryptionPassword != repeatEncryptionPassword) {
binding.repeatEncryptionPasswordLayout.error = getString(R.string.passwords_do_not_match)
return
return@launch
}
}
val key = if (isNullOrEmpty(encryptionPassword)) derivedKey else deriveKey(caldavAccount!!.username!!, encryptionPassword)
@ -106,10 +108,10 @@ class EncryptionSettingsActivity : ThemedInjectingAppCompatActivity(), Toolbar.O
CryptoManager(version, key, "userInfo")
} catch (e: VersionTooNewException) {
requestFailed(e)
return
return@launch
} catch (e: IntegrityException) {
requestFailed(e)
return
return@launch
}
if (userInfo == null) {
showProgressIndicator()

@ -7,6 +7,7 @@ import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.widget.Toolbar
import androidx.core.util.Pair
import androidx.lifecycle.lifecycleScope
import butterknife.OnCheckedChanged
import com.etesync.journalmanager.Crypto.CryptoManager
import com.etesync.journalmanager.Exceptions.IntegrityException
@ -17,6 +18,7 @@ import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.AndroidEntryPoint
import io.reactivex.Completable
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.launch
import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import org.tasks.caldav.BaseCaldavAccountSettingsActivity
@ -55,19 +57,19 @@ class EteSyncAccountSettingsActivity : BaseCaldavAccountSettingsActivity(), Tool
override val description: Int
get() = R.string.etesync_account_description
private fun addAccount(userInfoAndToken: Pair<UserInfoManager.UserInfo, String>) {
private suspend fun addAccount(userInfoAndToken: Pair<UserInfoManager.UserInfo, String>) {
caldavAccount = CaldavAccount()
caldavAccount!!.accountType = CaldavAccount.TYPE_ETESYNC
caldavAccount!!.uuid = UUIDHelper.newUUID()
applyTo(caldavAccount!!, userInfoAndToken)
}
private fun updateAccount(userInfoAndToken: Pair<UserInfoManager.UserInfo, String>) {
private suspend fun updateAccount(userInfoAndToken: Pair<UserInfoManager.UserInfo, String>) {
caldavAccount!!.error = ""
applyTo(caldavAccount!!, userInfoAndToken)
}
private fun applyTo(account: CaldavAccount, userInfoAndToken: Pair<UserInfoManager.UserInfo, String>) {
private suspend fun applyTo(account: CaldavAccount, userInfoAndToken: Pair<UserInfoManager.UserInfo, String>) {
hideProgressIndicator()
account.name = newName
account.url = newURL
@ -116,19 +118,17 @@ class EteSyncAccountSettingsActivity : BaseCaldavAccountSettingsActivity(), Tool
return super.needsValidation() || isNullOrEmpty(caldavAccount!!.encryptionKey)
}
override fun addAccount(url: String, username: String, password: String) {
override suspend fun addAccount(url: String, username: String, password: String) =
addAccountViewModel.addAccount(url, username, password)
}
override fun updateAccount(url: String, username: String, password: String?) {
override suspend fun updateAccount(url: String, username: String, password: String?) =
updateAccountViewModel.updateAccount(
url,
username,
if (PASSWORD_MASK == password) null else password,
caldavAccount!!.getPassword(encryption))
}
override fun updateAccount() {
override suspend fun updateAccount() {
caldavAccount!!.name = newName
saveAccountAndFinish()
}
@ -148,16 +148,18 @@ class EteSyncAccountSettingsActivity : BaseCaldavAccountSettingsActivity(), Tool
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_ENCRYPTION_PASSWORD) {
if (resultCode == Activity.RESULT_OK) {
val key = data!!.getStringExtra(EncryptionSettingsActivity.EXTRA_DERIVED_KEY)!!
caldavAccount!!.encryptionKey = encryption.encrypt(key)
saveAccountAndFinish()
lifecycleScope.launch {
val key = data!!.getStringExtra(EncryptionSettingsActivity.EXTRA_DERIVED_KEY)!!
caldavAccount!!.encryptionKey = encryption.encrypt(key)
saveAccountAndFinish()
}
}
} else {
super.onActivityResult(requestCode, resultCode, data)
}
}
private fun saveAccountAndFinish() {
private suspend fun saveAccountAndFinish() {
if (caldavAccount!!.id == Task.NO_ID) {
caldavDao.insert(caldavAccount!!)
} else {
@ -167,7 +169,7 @@ class EteSyncAccountSettingsActivity : BaseCaldavAccountSettingsActivity(), Tool
finish()
}
override fun removeAccount() {
override suspend fun removeAccount() {
if (caldavAccount != null) {
Completable.fromAction { eteSyncClient.forAccount(caldavAccount!!).invalidateToken() }
.subscribeOn(Schedulers.io())

@ -21,13 +21,13 @@ class EteSyncCalendarSettingsActivity : BaseCaldavCalendarSettingsActivity() {
updateCalendarViewModel.observe(this, { updateCalendar() }, this::requestFailed)
}
override fun createCalendar(caldavAccount: CaldavAccount, name: String, color: Int) =
override suspend fun createCalendar(caldavAccount: CaldavAccount, name: String, color: Int) =
createCalendarViewModel.createCalendar(caldavAccount, name, color)
override fun updateNameAndColor(
override suspend fun updateNameAndColor(
account: CaldavAccount, calendar: CaldavCalendar, name: String, color: Int) =
updateCalendarViewModel.updateCalendar(account, calendar, name, color)
override fun deleteCalendar(caldavAccount: CaldavAccount, caldavCalendar: CaldavCalendar) =
override suspend fun deleteCalendar(caldavAccount: CaldavAccount, caldavCalendar: CaldavCalendar) =
deleteCalendarViewModel.deleteCalendar(caldavAccount, caldavCalendar)
}

@ -7,7 +7,7 @@ import org.tasks.ui.CompletableViewModel
class UpdateCalendarViewModel @ViewModelInject constructor(
private val client: EteSyncClient): CompletableViewModel<String?>() {
fun updateCalendar(account: CaldavAccount, calendar: CaldavCalendar, name: String, color: Int) {
suspend fun updateCalendar(account: CaldavAccount, calendar: CaldavCalendar, name: String, color: Int) {
run { client.forAccount(account).updateCollection(calendar, name, color) }
}
}

@ -8,7 +8,7 @@ import org.tasks.ui.CompletableViewModel
class UpdateEteSyncAccountViewModel @ViewModelInject constructor(
private val client: EteSyncClient) : CompletableViewModel<Pair<UserInfo, String>>() {
fun updateAccount(url: String, user: String, pass: String?, token: String) {
suspend fun updateAccount(url: String, user: String, pass: String?, token: String) {
run {
client.setForeground()
if (isNullOrEmpty(pass)) {

@ -1,14 +1,8 @@
package org.tasks.ui
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.observe
import com.todoroo.andlib.utility.AndroidUtilities
import io.reactivex.Completable
import io.reactivex.android.schedulers.AndroidSchedulers
import androidx.lifecycle.*
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.launch
open class ActionViewModel : ViewModel() {
private val completed = MutableLiveData<Boolean>()
@ -20,25 +14,26 @@ open class ActionViewModel : ViewModel() {
fun observe(
lifecycleOwner: LifecycleOwner,
completeObserver: (Boolean) -> Unit,
completeObserver: suspend (Boolean) -> Any,
errorObserver: (Throwable) -> Unit) {
completed.observe(lifecycleOwner, completeObserver)
completed.observe(lifecycleOwner) {
lifecycleOwner.lifecycleScope.launch {
completeObserver.invoke(it)
}
}
error.observe(lifecycleOwner, errorObserver)
}
protected fun run(action: () -> Unit) {
AndroidUtilities.assertMainThread()
protected suspend fun run(action: suspend () -> Unit) {
if (!inProgress) {
inProgress = true
disposables.add(
Completable.fromAction(action)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doFinally {
AndroidUtilities.assertMainThread()
inProgress = false
}
.subscribe({ completed.setValue(true) }) { value: Throwable -> error.setValue(value) })
try {
action.invoke()
completed.value = true
} catch (e: Exception) {
error.value = e
}
inProgress = false
}
}

@ -1,14 +1,8 @@
package org.tasks.ui
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.observe
import com.todoroo.andlib.utility.AndroidUtilities
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import androidx.lifecycle.*
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.launch
abstract class CompletableViewModel<T> : ViewModel() {
private val data = MutableLiveData<T>()
@ -20,25 +14,25 @@ abstract class CompletableViewModel<T> : ViewModel() {
fun observe(
lifecycleOwner: LifecycleOwner,
dataObserver: (T) -> Unit,
dataObserver: suspend (T) -> Unit,
errorObserver: (Throwable) -> Unit) {
data.observe(lifecycleOwner, dataObserver)
data.observe(lifecycleOwner) {
lifecycleOwner.lifecycleScope.launch {
dataObserver.invoke(it)
}
}
error.observe(lifecycleOwner, errorObserver)
}
protected fun run(callable: () -> T) {
AndroidUtilities.assertMainThread()
protected suspend fun run(callable: suspend () -> T) {
if (!inProgress) {
inProgress = true
disposables.add(
Single.fromCallable(callable)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doFinally {
AndroidUtilities.assertMainThread()
inProgress = false
}
.subscribe({ value: T -> data.setValue(value) }) { value: Throwable -> error.setValue(value) })
try {
data.value = callable.invoke()
} catch (e: Exception) {
error.value = e
}
inProgress = false
}
}

Loading…
Cancel
Save