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() localBroadcastManager.broadcastRefreshList()
} }
fun delete(list: GoogleTaskAccount) = runBlocking { suspend fun delete(list: GoogleTaskAccount) {
val tasks = deletionDao.delete(list) val tasks = deletionDao.delete(list)
delete(tasks) delete(tasks)
localBroadcastManager.broadcastRefreshList() localBroadcastManager.broadcastRefreshList()
} }
fun delete(list: CaldavCalendar) = runBlocking { suspend fun delete(list: CaldavCalendar) {
val tasks = deletionDao.delete(list) val tasks = deletionDao.delete(list)
delete(tasks) delete(tasks)
localBroadcastManager.broadcastRefreshList() localBroadcastManager.broadcastRefreshList()
} }
fun delete(list: CaldavAccount) = runBlocking { suspend fun delete(list: CaldavAccount) {
val tasks = deletionDao.delete(list) val tasks = deletionDao.delete(list)
delete(tasks) delete(tasks)
localBroadcastManager.broadcastRefreshList() localBroadcastManager.broadcastRefreshList()

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

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

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

@ -37,6 +37,7 @@ import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R import org.tasks.R
import org.tasks.Strings import org.tasks.Strings
import org.tasks.data.Filter import org.tasks.data.Filter
import org.tasks.data.FilterDao
import org.tasks.data.FilterDaoBlocking import org.tasks.data.FilterDaoBlocking
import org.tasks.filters.FilterCriteriaProvider import org.tasks.filters.FilterCriteriaProvider
import org.tasks.locale.Locale import org.tasks.locale.Locale
@ -46,7 +47,7 @@ import kotlin.math.max
@AndroidEntryPoint @AndroidEntryPoint
class FilterSettingsActivity : BaseListSettingsActivity() { class FilterSettingsActivity : BaseListSettingsActivity() {
@Inject lateinit var filterDao: FilterDaoBlocking @Inject lateinit var filterDao: FilterDao
@Inject lateinit var locale: Locale @Inject lateinit var locale: Locale
@Inject lateinit var database: Database @Inject lateinit var database: Database
@Inject lateinit var filterCriteriaProvider: FilterCriteriaProvider @Inject lateinit var filterCriteriaProvider: FilterCriteriaProvider
@ -224,7 +225,7 @@ class FilterSettingsActivity : BaseListSettingsActivity() {
nameLayout.error = null nameLayout.error = null
} }
override fun save() { override suspend fun save() {
val newName = newName val newName = newName
if (Strings.isNullOrEmpty(newName)) { if (Strings.isNullOrEmpty(newName)) {
nameLayout.error = getString(R.string.name_cannot_be_empty) nameLayout.error = getString(R.string.name_cannot_be_empty)
@ -277,7 +278,7 @@ class FilterSettingsActivity : BaseListSettingsActivity() {
override val layout: Int override val layout: Int
get() = R.layout.filter_settings_activity get() = R.layout.filter_settings_activity
override fun delete() { override suspend fun delete() {
filterDao.delete(filter!!.id) filterDao.delete(filter!!.id)
setResult( setResult(
Activity.RESULT_OK, Intent(TaskListFragment.ACTION_DELETED).putExtra(TOKEN_FILTER, filter)) 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.MainActivity
import com.todoroo.astrid.activity.TaskListFragment import com.todoroo.astrid.activity.TaskListFragment
import com.todoroo.astrid.api.GtasksFilter import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.gtasks.GtasksListService
import com.todoroo.astrid.gtasks.api.GtasksInvoker import com.todoroo.astrid.gtasks.api.GtasksInvoker
import com.todoroo.astrid.service.TaskDeleter import com.todoroo.astrid.service.TaskDeleter
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -24,15 +23,14 @@ import org.tasks.R
import org.tasks.Strings.isNullOrEmpty import org.tasks.Strings.isNullOrEmpty
import org.tasks.data.GoogleTaskAccount import org.tasks.data.GoogleTaskAccount
import org.tasks.data.GoogleTaskList import org.tasks.data.GoogleTaskList
import org.tasks.data.GoogleTaskListDaoBlocking import org.tasks.data.GoogleTaskListDao
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class GoogleTaskListSettingsActivity : BaseListSettingsActivity() { class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
@Inject @ApplicationContext lateinit var context: Context @Inject @ApplicationContext lateinit var context: Context
@Inject lateinit var googleTaskListDao: GoogleTaskListDaoBlocking @Inject lateinit var googleTaskListDao: GoogleTaskListDao
@Inject lateinit var gtasksListService: GtasksListService
@Inject lateinit var taskDeleter: TaskDeleter @Inject lateinit var taskDeleter: TaskDeleter
@Inject lateinit var gtasksInvoker: GtasksInvoker @Inject lateinit var gtasksInvoker: GtasksInvoker
@ -93,7 +91,7 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
private fun requestInProgress() = progressView.visibility == View.VISIBLE private fun requestInProgress() = progressView.visibility == View.VISIBLE
override fun save() { override suspend fun save() {
if (requestInProgress()) { if (requestInProgress()) {
return return
} }
@ -141,7 +139,7 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
} }
} }
override fun delete() { override suspend fun delete() {
showProgressIndicator() showProgressIndicator()
deleteListViewModel.deleteList(gtasksList) deleteListViewModel.deleteList(gtasksList)
} }
@ -167,7 +165,7 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
private fun nameChanged() = newName != gtasksList.title private fun nameChanged() = newName != gtasksList.title
private fun onListCreated(taskList: TaskList) { private suspend fun onListCreated(taskList: TaskList) {
gtasksList.remoteId = taskList.id gtasksList.remoteId = taskList.id
gtasksList.title = taskList.title gtasksList.title = taskList.title
gtasksList.setColor(selectedColor) gtasksList.setColor(selectedColor)
@ -176,10 +174,9 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
setResult( setResult(
Activity.RESULT_OK, Intent().putExtra(MainActivity.OPEN_FILTER, GtasksFilter(gtasksList))) Activity.RESULT_OK, Intent().putExtra(MainActivity.OPEN_FILTER, GtasksFilter(gtasksList)))
finish() finish()
return
} }
private fun onListDeleted(deleted: Boolean) { private suspend fun onListDeleted(deleted: Boolean) {
if (deleted) { if (deleted) {
taskDeleter.delete(gtasksList) taskDeleter.delete(gtasksList)
setResult(Activity.RESULT_OK, Intent(TaskListFragment.ACTION_DELETED)) 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.title = taskList.title
gtasksList.setColor(selectedColor) gtasksList.setColor(selectedColor)
gtasksList.setIcon(selectedIcon) gtasksList.setIcon(selectedIcon)
@ -197,7 +194,6 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
Intent(TaskListFragment.ACTION_RELOAD) Intent(TaskListFragment.ACTION_RELOAD)
.putExtra(MainActivity.OPEN_FILTER, GtasksFilter(gtasksList))) .putExtra(MainActivity.OPEN_FILTER, GtasksFilter(gtasksList)))
finish() finish()
return
} }
private fun requestFailed(error: Throwable) { private fun requestFailed(error: Throwable) {

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

@ -8,7 +8,7 @@ import org.tasks.ui.CompletableViewModel
class RenameListViewModel @ViewModelInject constructor( class RenameListViewModel @ViewModelInject constructor(
private val invoker: GtasksInvoker) : CompletableViewModel<TaskList>() { 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)!! } 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 dagger.hilt.android.AndroidEntryPoint
import org.tasks.R import org.tasks.R
import org.tasks.Strings.isNullOrEmpty import org.tasks.Strings.isNullOrEmpty
import org.tasks.data.TagDaoBlocking import org.tasks.data.TagDao
import org.tasks.data.TagData import org.tasks.data.TagData
import org.tasks.data.TagDataDaoBlocking import org.tasks.data.TagDataDao
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class TagSettingsActivity : BaseListSettingsActivity() { class TagSettingsActivity : BaseListSettingsActivity() {
@Inject lateinit var tagDataDao: TagDataDaoBlocking @Inject lateinit var tagDataDao: TagDataDao
@Inject lateinit var tagDao: TagDaoBlocking @Inject lateinit var tagDao: TagDao
@BindView(R.id.name) @BindView(R.id.name)
lateinit var name: TextInputEditText lateinit var name: TextInputEditText
@ -78,12 +78,12 @@ class TagSettingsActivity : BaseListSettingsActivity() {
private val newName: String private val newName: String
get() = name.text.toString().trim { it <= ' ' } 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)) return ((isNewTag || !newName.equals(tagData.name, ignoreCase = true))
&& tagDataDao.getTagByName(newName) != null) && tagDataDao.getTagByName(newName) != null)
} }
override fun save() { override suspend fun save() {
val newName = newName val newName = newName
if (isNullOrEmpty(newName)) { if (isNullOrEmpty(newName)) {
nameLayout.error = getString(R.string.name_cannot_be_empty) nameLayout.error = getString(R.string.name_cannot_be_empty)
@ -132,7 +132,7 @@ class TagSettingsActivity : BaseListSettingsActivity() {
override val layout: Int override val layout: Int
get() = R.layout.activity_tag_settings get() = R.layout.activity_tag_settings
override fun delete() { override suspend fun delete() {
val uuid = tagData.remoteId val uuid = tagData.remoteId
tagDataDao.delete(tagData) tagDataDao.delete(tagData)
setResult( setResult(

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

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

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

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

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

@ -6,7 +6,7 @@ import org.tasks.ui.CompletableViewModel
class CreateCalendarViewModel @ViewModelInject constructor( class CreateCalendarViewModel @ViewModelInject constructor(
private val client: CaldavClient): CompletableViewModel<String?>() { 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) } run { client.forAccount(account).makeCollection(name, color) }
} }
} }

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

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

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

@ -7,7 +7,7 @@ import org.tasks.ui.CompletableViewModel
class UpdateCalendarViewModel @ViewModelInject constructor( class UpdateCalendarViewModel @ViewModelInject constructor(
private val client: CaldavClient) : CompletableViewModel<String?>() { 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) } run { client.forCalendar(account, calendar).updateCollection(name, color) }
} }
} }

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

@ -6,7 +6,7 @@ import org.tasks.ui.CompletableViewModel
class CreateCalendarViewModel @ViewModelInject constructor( class CreateCalendarViewModel @ViewModelInject constructor(
private val client: EteSyncClient) : CompletableViewModel<String?>() { 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) } run { client.forAccount(account).makeCollection(name, color) }
} }
} }

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

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

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

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

@ -21,13 +21,13 @@ class EteSyncCalendarSettingsActivity : BaseCaldavCalendarSettingsActivity() {
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) createCalendarViewModel.createCalendar(caldavAccount, name, color)
override fun updateNameAndColor( override suspend fun updateNameAndColor(
account: CaldavAccount, calendar: CaldavCalendar, name: String, color: Int) = account: CaldavAccount, calendar: CaldavCalendar, name: String, color: Int) =
updateCalendarViewModel.updateCalendar(account, calendar, name, color) 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) deleteCalendarViewModel.deleteCalendar(caldavAccount, caldavCalendar)
} }

@ -7,7 +7,7 @@ import org.tasks.ui.CompletableViewModel
class UpdateCalendarViewModel @ViewModelInject constructor( class UpdateCalendarViewModel @ViewModelInject constructor(
private val client: EteSyncClient): CompletableViewModel<String?>() { 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) } run { client.forAccount(account).updateCollection(calendar, name, color) }
} }
} }

@ -8,7 +8,7 @@ import org.tasks.ui.CompletableViewModel
class UpdateEteSyncAccountViewModel @ViewModelInject constructor( class UpdateEteSyncAccountViewModel @ViewModelInject constructor(
private val client: EteSyncClient) : CompletableViewModel<Pair<UserInfo, String>>() { 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 { run {
client.setForeground() client.setForeground()
if (isNullOrEmpty(pass)) { if (isNullOrEmpty(pass)) {

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

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

Loading…
Cancel
Save