Use coroutines in task creator

pull/1055/head
Alex Baker 4 years ago
parent 6e6fb3eada
commit c3c5de1e5c

@ -9,9 +9,10 @@ import com.todoroo.astrid.data.Task
import com.todoroo.astrid.utility.TitleParser
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import org.tasks.data.TagDataDaoBlocking
import org.tasks.data.TagDataDao
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import java.util.*
@ -21,7 +22,7 @@ import javax.inject.Inject
@HiltAndroidTest
class QuickAddMarkupTest : InjectingTestCase() {
private val tags = ArrayList<String>()
@Inject lateinit var tagDataDao: TagDataDaoBlocking
@Inject lateinit var tagDataDao: TagDataDao
private var task: Task? = null
@ -81,7 +82,7 @@ class QuickAddMarkupTest : InjectingTestCase() {
assertEquals(title, task!!.title)
}
private fun whenTitleIs(title: String) {
private fun whenTitleIs(title: String) = runBlocking {
task = Task()
task!!.title = title
tags.clear()

@ -11,11 +11,12 @@ import com.todoroo.astrid.data.Task
import com.todoroo.astrid.utility.TitleParser
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
import org.tasks.R
import org.tasks.data.TagDataDaoBlocking
import org.tasks.data.TagDataDao
import org.tasks.date.DateTimeUtils
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
@ -26,7 +27,7 @@ import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@HiltAndroidTest
class TitleParserTest : InjectingTestCase() {
@Inject lateinit var tagDataDao: TagDataDaoBlocking
@Inject lateinit var tagDataDao: TagDataDao
@Inject lateinit var preferences: Preferences
@Inject lateinit var taskCreator: TaskCreator
@ -41,7 +42,7 @@ class TitleParserTest : InjectingTestCase() {
* repeat, no lists
*/
@Test
fun testNoRegexes() {
fun testNoRegexes() = runBlocking {
val task = taskCreator.basicQuickAddTask("Jog")
val nothing = Task()
assertFalse(task.hasDueTime())
@ -147,13 +148,13 @@ class TitleParserTest : InjectingTestCase() {
}
}
private fun insertTitleAddTask(title: String): Task {
return taskCreator.createWithValues(title)
private fun insertTitleAddTask(title: String): Task = runBlocking {
taskCreator.createWithValues(title)
}
// ----------------Days begin----------------//
@Test
fun testDays() {
fun testDays() = runBlocking {
val today = Calendar.getInstance()
var title = "Jog today"
var task = taskCreator.createWithValues(title)
@ -182,7 +183,7 @@ class TitleParserTest : InjectingTestCase() {
// ----------------Priority begin----------------//
/** tests all words using priority 0 */
@Test
fun testPriority0() {
fun testPriority0() = runBlocking {
val acceptedStrings = arrayOf("priority 0", "least priority", "lowest priority", "bang 0")
for (acceptedString in acceptedStrings) {
val title = "Jog $acceptedString"
@ -197,7 +198,7 @@ class TitleParserTest : InjectingTestCase() {
}
@Test
fun testPriority1() {
fun testPriority1() = runBlocking {
val acceptedStringsAtEnd = arrayOf("priority 1", "low priority", "bang", "bang 1")
val acceptedStringsAnywhere = arrayOf("!1", "!")
var task: Task
@ -222,7 +223,7 @@ class TitleParserTest : InjectingTestCase() {
}
@Test
fun testPriority2() {
fun testPriority2() = runBlocking {
val acceptedStringsAtEnd = arrayOf("priority 2", "high priority", "bang bang", "bang 2")
val acceptedStringsAnywhere = arrayOf("!2", "!!")
for (acceptedStringAtEnd in acceptedStringsAtEnd) {
@ -244,7 +245,7 @@ class TitleParserTest : InjectingTestCase() {
}
@Test
fun testPriority3() {
fun testPriority3() = runBlocking {
val acceptedStringsAtEnd = arrayOf(
"priority 3",
"highest priority",
@ -274,7 +275,7 @@ class TitleParserTest : InjectingTestCase() {
// ----------------Repeats begin----------------//
/** test daily repeat from due date, but with no due date set */
@Test
fun testDailyWithNoDueDate() {
fun testDailyWithNoDueDate() = runBlocking {
var title = "Jog daily"
var task = taskCreator.createWithValues(title)
val rrule = RRule()
@ -300,7 +301,7 @@ class TitleParserTest : InjectingTestCase() {
/** test weekly repeat from due date, with no due date & time set */
@Test
fun testWeeklyWithNoDueDate() {
fun testWeeklyWithNoDueDate() = runBlocking {
var title = "Jog weekly"
var task = taskCreator.createWithValues(title)
val rrule = RRule()
@ -326,7 +327,7 @@ class TitleParserTest : InjectingTestCase() {
/** test hourly repeat from due date, with no due date but no time */
@Test
fun testMonthlyFromNoDueDate() {
fun testMonthlyFromNoDueDate() = runBlocking {
var title = "Jog monthly"
var task = taskCreator.createWithValues(title)
val rrule = RRule()
@ -351,7 +352,7 @@ class TitleParserTest : InjectingTestCase() {
}
@Test
fun testDailyFromDueDate() {
fun testDailyFromDueDate() = runBlocking {
var title = "Jog daily starting from today"
var task = taskCreator.createWithValues(title)
val rrule = RRule()
@ -373,7 +374,7 @@ class TitleParserTest : InjectingTestCase() {
}
@Test
fun testWeeklyFromDueDate() {
fun testWeeklyFromDueDate() = runBlocking {
var title = "Jog weekly starting from today"
var task = taskCreator.createWithValues(title)
val rrule = RRule()
@ -397,7 +398,7 @@ class TitleParserTest : InjectingTestCase() {
// ----------------Tags begin----------------//
/** tests all words using priority 0 */
@Test
fun testTagsPound() {
fun testTagsPound() = runBlocking {
val acceptedStrings = arrayOf("#tag", "#a", "#(a cool tag)", "#(cool)")
var task: Task
for (acceptedString in acceptedStrings) {
@ -414,7 +415,7 @@ class TitleParserTest : InjectingTestCase() {
/** tests all words using priority 0 */
@Test
fun testTagsAt() {
fun testTagsAt() = runBlocking {
val acceptedStrings = arrayOf("@tag", "@a", "@(a cool tag)", "@(cool)")
var task: Task
for (acceptedString in acceptedStrings) {

@ -148,7 +148,7 @@ class MainActivity : InjectingAppCompatActivity(), TaskListFragmentCallbackHandl
navigationDrawer.closeDrawer()
}
private fun getTaskToLoad(filter: Filter?): Task? {
private suspend fun getTaskToLoad(filter: Filter?): Task? {
val intent = intent
if (intent.isFromHistory) {
return null
@ -165,7 +165,7 @@ class MainActivity : InjectingAppCompatActivity(), TaskListFragmentCallbackHandl
return null
}
private fun openTask(filter: Filter?) {
private fun openTask(filter: Filter?) = lifecycleScope.launch {
val task = getTaskToLoad(filter)
when {
task != null -> onTaskListItemClicked(task)
@ -344,30 +344,28 @@ class MainActivity : InjectingAppCompatActivity(), TaskListFragmentCallbackHandl
private val nightMode: Int
get() = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
override fun onTaskListItemClicked(task: Task?) {
override suspend fun onTaskListItemClicked(task: Task?) {
AndroidUtilities.assertMainThread()
if (task == null) {
return
}
lifecycleScope.launchWhenResumed {
taskEditFragment?.let {
it.editViewModel.cleared.removeObservers(this@MainActivity)
it.save()
}
clearUi()
val fragment = newTaskEditFragment(
task,
defaultFilterProvider.getList(task),
locationDao.getLocation(task, preferences),
tagDataDao.getTags(task),
alarmDao.getAlarms(task),
filterColor)
supportFragmentManager.beginTransaction()
.replace(R.id.detail, fragment, TaskEditFragment.TAG_TASKEDIT_FRAGMENT)
.addToBackStack(TaskEditFragment.TAG_TASKEDIT_FRAGMENT)
.commit()
showDetailFragment()
taskEditFragment?.let {
it.editViewModel.cleared.removeObservers(this@MainActivity)
it.save()
}
clearUi()
val fragment = newTaskEditFragment(
task,
defaultFilterProvider.getList(task),
locationDao.getLocation(task, preferences),
tagDataDao.getTags(task),
alarmDao.getAlarms(task),
filterColor)
supportFragmentManager.beginTransaction()
.replace(R.id.detail, fragment, TaskEditFragment.TAG_TASKEDIT_FRAGMENT)
.addToBackStack(TaskEditFragment.TAG_TASKEDIT_FRAGMENT)
.commit()
showDetailFragment()
}
override fun onNavigationIconClicked() {

@ -4,12 +4,14 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.lifecycle.lifecycleScope
import com.google.common.collect.Lists
import com.google.common.io.Files
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.service.TaskCreator
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.launch
import org.tasks.Strings.isNullOrEmpty
import org.tasks.data.TaskAttachment
import org.tasks.files.FileHelper
@ -35,31 +37,39 @@ class ShareLinkActivity : InjectingAppCompatActivity() {
super.onCreate(savedInstanceState)
val intent = intent
val action = intent.action
if (Intent.ACTION_PROCESS_TEXT == action) {
val text = intent.getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT)
if (text != null) {
val task = taskCreator.createWithValues(text.toString())
when {
Intent.ACTION_PROCESS_TEXT == action -> lifecycleScope.launch {
val text = intent.getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT)
if (text != null) {
val task = taskCreator.createWithValues(text.toString())
editTask(task)
}
finish()
}
Intent.ACTION_SEND == action -> lifecycleScope.launch {
val subject = intent.getStringExtra(Intent.EXTRA_SUBJECT)
val task = taskCreator.createWithValues(subject)
task.notes = intent.getStringExtra(Intent.EXTRA_TEXT)
if (hasAttachments(intent)) {
task.putTransitory(TaskAttachment.KEY, copyAttachment(intent))
}
editTask(task)
finish()
}
} else if (Intent.ACTION_SEND == action) {
val subject = intent.getStringExtra(Intent.EXTRA_SUBJECT)
val task = taskCreator.createWithValues(subject)
task.notes = intent.getStringExtra(Intent.EXTRA_TEXT)
if (hasAttachments(intent)) {
task.putTransitory(TaskAttachment.KEY, copyAttachment(intent))
Intent.ACTION_SEND_MULTIPLE == action -> lifecycleScope.launch {
val task = taskCreator.createWithValues(intent.getStringExtra(Intent.EXTRA_SUBJECT))
task.notes = intent.getStringExtra(Intent.EXTRA_TEXT)
if (hasAttachments(intent)) {
task.putTransitory(TaskAttachment.KEY, copyMultipleAttachments(intent))
}
editTask(task)
finish()
}
editTask(task)
} else if (Intent.ACTION_SEND_MULTIPLE == action) {
val task = taskCreator.createWithValues(intent.getStringExtra(Intent.EXTRA_SUBJECT))
task.notes = intent.getStringExtra(Intent.EXTRA_TEXT)
if (hasAttachments(intent)) {
task.putTransitory(TaskAttachment.KEY, copyMultipleAttachments(intent))
else -> {
Timber.e("Unhandled intent: %s", intent)
finish()
}
editTask(task)
} else {
Timber.e("Unhandled intent: %s", intent)
}
finish()
}
private fun editTask(task: Task) {

@ -420,11 +420,13 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
@OnClick(R.id.fab)
fun createNewTask() {
shortcutManager.reportShortcutUsed(ShortcutManager.SHORTCUT_NEW_TASK)
onTaskListItemClicked(addTask(""))
lifecycleScope.launch {
shortcutManager.reportShortcutUsed(ShortcutManager.SHORTCUT_NEW_TASK)
onTaskListItemClicked(addTask(""))
}
}
private fun addTask(title: String): Task {
private suspend fun addTask(title: String): Task {
return taskCreator.createWithValues(filter, title)
}
@ -517,12 +519,14 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
VOICE_RECOGNITION_REQUEST_CODE -> if (resultCode == Activity.RESULT_OK) {
val match: List<String>? = data!!.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
if (match != null && match.isNotEmpty() && match[0].isNotEmpty()) {
var recognizedSpeech = match[0]
recognizedSpeech = (recognizedSpeech.substring(0, 1).toUpperCase()
+ recognizedSpeech.substring(1).toLowerCase())
onTaskListItemClicked(addTask(recognizedSpeech))
lifecycleScope.launch {
val match: List<String>? = data!!.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
if (match != null && match.isNotEmpty() && match[0].isNotEmpty()) {
var recognizedSpeech = match[0]
recognizedSpeech = (recognizedSpeech.substring(0, 1).toUpperCase()
+ recognizedSpeech.substring(1).toLowerCase())
onTaskListItemClicked(addTask(recognizedSpeech))
}
}
}
REQUEST_MOVE_TASKS -> if (resultCode == Activity.RESULT_OK) {
@ -560,7 +564,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
return onOptionsItemSelected(item)
}
fun onTaskListItemClicked(task: Task?) {
fun onTaskListItemClicked(task: Task?) = lifecycleScope.launch {
callbacks.onTaskListItemClicked(task)
}
@ -712,7 +716,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
}
interface TaskListFragmentCallbackHandler {
fun onTaskListItemClicked(task: Task?)
suspend fun onTaskListItemClicked(task: Task?)
fun onNavigationIconClicked()
}

@ -5,7 +5,7 @@ import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.api.PermaSql
import com.todoroo.astrid.dao.TaskDaoBlocking
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.data.Task.Companion.createDueDate
import com.todoroo.astrid.gcal.GCalHelper
@ -23,14 +23,15 @@ import javax.inject.Inject
class TaskCreator @Inject constructor(
private val gcalHelper: GCalHelper,
private val preferences: Preferences,
private val tagDataDao: TagDataDaoBlocking,
private val taskDao: TaskDaoBlocking,
private val tagDao: TagDaoBlocking,
private val googleTaskDao: GoogleTaskDaoBlocking,
private val tagDataDao: TagDataDao,
private val taskDao: TaskDao,
private val tagDao: TagDao,
private val googleTaskDao: GoogleTaskDao,
private val defaultFilterProvider: DefaultFilterProvider,
private val caldavDao: CaldavDaoBlocking,
private val locationDao: LocationDaoBlocking) {
fun basicQuickAddTask(title: String): Task {
private val caldavDao: CaldavDao,
private val locationDao: LocationDao) {
suspend fun basicQuickAddTask(title: String): Task {
var title = title
title = title.trim { it <= ' ' }
val task = createWithValues(title)
@ -51,7 +52,7 @@ class TaskCreator @Inject constructor(
caldavDao.insert(
task, CaldavTask(task.id, task.getTransitory<String>(CaldavTask.KEY)), addToTop)
} else {
val remoteList = defaultFilterProvider.defaultList
val remoteList = defaultFilterProvider.getDefaultList()
if (remoteList is GtasksFilter) {
googleTaskDao.insertAndShift(
GoogleTask(task.id, remoteList.remoteId), addToTop)
@ -70,11 +71,11 @@ class TaskCreator @Inject constructor(
return task
}
fun createWithValues(title: String?): Task {
suspend fun createWithValues(title: String?): Task {
return create(null, title)
}
fun createWithValues(filter: Filter?, title: String?): Task {
suspend fun createWithValues(filter: Filter?, title: String?): Task {
return create(filter?.valuesForNewTasks, title)
}
@ -82,7 +83,7 @@ class TaskCreator @Inject constructor(
* Create task from the given content values, saving it. This version doesn't need to start with a
* base task model.
*/
private fun create(values: Map<String, Any>?, title: String?): Task {
private suspend fun create(values: Map<String, Any>?, title: String?): Task {
val task = Task()
task.creationDate = DateUtilities.now()
task.modificationDate = DateUtilities.now()
@ -128,7 +129,7 @@ class TaskCreator @Inject constructor(
return task
}
fun createTags(task: Task) {
suspend fun createTags(task: Task) {
for (tag in task.tags) {
var tagData = tagDataDao.getTagByName(tag)
if (tagData == null) {

@ -12,14 +12,14 @@ import com.mdimension.jchronic.Chronic
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.data.Task.Companion.createDueDate
import org.tasks.Strings.isNullOrEmpty
import org.tasks.data.TagDataDaoBlocking
import org.tasks.data.TagDataDao
import timber.log.Timber
import java.util.*
import java.util.regex.Matcher
import java.util.regex.Pattern
object TitleParser {
fun parse(tagDataDao: TagDataDaoBlocking, task: Task, tags: ArrayList<String>) {
suspend fun parse(tagDataDao: TagDataDao, task: Task, tags: ArrayList<String>) {
repeatHelper(task)
listHelper(
tagDataDao,
@ -39,7 +39,7 @@ object TitleParser {
} else pattern
}
fun listHelper(tagDataDao: TagDataDaoBlocking, task: Task, tags: ArrayList<String>) {
suspend fun listHelper(tagDataDao: TagDataDao, task: Task, tags: ArrayList<String>) {
var inputText = task.title
val tagPattern = Pattern.compile("(\\s|^)#(\\(.*\\)|[^\\s]+)")
val contextPattern = Pattern.compile("(\\s|^)@(\\(.*\\)|[^\\s]+)")

@ -118,14 +118,16 @@ class SubtaskControlSet : TaskEditControlFragment(), SubtaskViewHolder.Callbacks
fun addSubtask() {
if (isGoogleTaskChild) {
toaster.longToast(R.string.subtasks_multilevel_google_task)
return
} else {
lifecycleScope.launch {
val task = taskCreator.createWithValues("")
viewModel.newSubtasks.add(task)
val editText = addSubtask(task)
editText.requestFocus()
val imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT)
}
}
val task = taskCreator.createWithValues("")
viewModel.newSubtasks.add(task)
val editText = addSubtask(task)
editText.requestFocus()
val imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT)
}
private fun addSubtask(task: Task): EditText {

Loading…
Cancel
Save